diff options
822 files changed, 147870 insertions, 15415 deletions
diff --git a/.gitattributes b/.gitattributes index e34533a0d..d3aa9bed2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,21 +1,38 @@ # Set default behaviour, in case users don't have core.autocrlf set. * text=auto -# Explicitly declare text files we want to always be normalized and converted +# Explicitly declare text files we want to always be normalized and converted # to native line endings on checkout. -*.py text -*.js text -*.po text +*.bat text +*.c text *.cfg text -*.md text +*.cmd text +*.coffee text +*.conf text +*.htm text +*.html text *.in text -*.txt text -*.sh text +*.js text *.json text -*.html text -.htm text +*.md text +*.po text +*.pot text +*.py text +*.rst text +*.sh text +*.thrift text +*.txt text +*.xml text +*.yaml text # Denote all files that are truly binary and should not be modified. -*.png binary +*.gif binary +*.ico binary *.jpg binary -*.mo binary
\ No newline at end of file +*.mo binary +*.pyc binary +*.pyx binary +*.png binary +*.rar binary +*.svg binary +*.zip binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..061269bbd --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# Common packaging directories +/bin/ +/build/ +/dist/ +/env/ +/lib/ +/lib64/ +/parts/ +/sdist/ +/var/ +/temp/ + +# Common directories +.*/ +__pycache__/ +Downloads/ +Logs/ +tmp/ +userplugins/ + +# Common files +*.backup +*.db +*.pid +/*.conf +/*.version +/*.txt +/*.xml +/*.zip +/module/config/core.xml +/module/config/plugin.xml + +# Common MacOS & Windows files +*.DS_Store +Thumbs.db +desktop.ini + +# Certificate files +cert.pem +ssl.crt +ssl.key + +# Common compiled files +*.mo +*.so +*.py[cod] +!/pyload/plugins/container/DLC_*.py[cod] + +# Installer files +.installed.cfg +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml + +# Python Eggs +*.egg +*.egg-info +develop-eggs +eggs + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# PyCharm +.idea + +# Other development stuff +.svn +*~ +*.orig +*.pidaproject +*.prefs +*.project +*.pydevproject +*.rej +/docs/_build/ +/pyload/ +DLC_*.py +paver-minilib.zip diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 1215b241d..000000000 --- a/.hgignore +++ /dev/null @@ -1,36 +0,0 @@ -# ignoreing unneeded files, using glob syntax -syntax: glob -*.pyc -*~ -*.pidaproject -.svn -*.DS_Store -*.egg-info -*.project -*.pydevproject -Downloads/* -container/* -Logs/* -docs/module/ -docs/_build -module/plugins/container/DLC_*.py -failed_links.txt -module/config/gui.xml -module/config/core.xml -module/config/plugin.xml -links.txt -ssl.crt -ssl.key -cert.pem -module/web/pyload.db -*.svg -*.prefs -*.po -*.orig -*.rej -pyload/* -dist/* -build/* -setup.py -paver-minilib.zip -env/* diff --git a/CREDITS.md b/CREDITS.md new file mode 100644 index 000000000..8e0f86740 --- /dev/null +++ b/CREDITS.md @@ -0,0 +1,38 @@ +Credits +------- + +### pyLoad Team ### + +*(alphabetically sorted)* + + - himbrr <himbrr@himbrr.ws> + - Marius <mkaay@mkaay.de> + - RaNaN <Mast3rRaNaN@hotmail.de> + - sebnapi + - spoob <spoob@gmx.de> + - Stefano <l.stickell@yahoo.it> + - Walter Purcaro <vuolter@gmail.com> + - zoidberg10 <zoidberg@mujmail.cz> + +A special thanks to spoob, sebnapi and RaNaN who created pyLoad! + + +### Contributors ### + +The list of developers who have kindly contributed to the pyLoad project is constantly updated. +You can found it here: <https://github.com/pyload/pyload/graphs/contributors>. + + +### Translators ### + +Many users contribute everyday to translate pyLoad in more and more languages. +You can see their recent activities here: <http://translate.pyload.org/project/pyload/activity_stream>. + + +### Supporters ### + +Sadly, is really hard to list all the users who helped the pyLoad Team in these last years testing code, reporting issues, +opening topic to share tips and advices, fix troubles or simply discuss about this project... + + +#### The pyLoad Team can be only forever thankful to all of you for your amazing efforts! #### diff --git a/LICENSE b/LICENSE deleted file mode 100644 index bc08fe2e4..000000000 --- a/LICENSE +++ /dev/null @@ -1,619 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..78f62ade3 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,596 @@ +GNU GENERAL PUBLIC LICENSE +========================== + +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. <<http://fsf.org/>> + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +## Preamble + +The GNU General Public License is a free, copyleft license for software and other +kinds of works. + +The licenses for most software and other practical works are designed to take away +your freedom to share and change the works. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change all versions of a +program--to make sure it remains free software for all its users. We, the Free +Software Foundation, use the GNU General Public License for most of our software; it +applies also to any other work released this way by its authors. You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General +Public Licenses are designed to make sure that you have the freedom to distribute +copies of free software (and charge for them if you wish), that you receive source +code or can get it if you want it, that you can change the software or use pieces of +it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or +asking you to surrender the rights. Therefore, you have certain responsibilities if +you distribute copies of the software, or if you modify it: responsibilities to +respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, +you must pass on to the recipients the same freedoms that you received. You must make +sure that they, too, receive or can get the source code. And you must show them these +terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert +copyright on the software, and (2) offer you this License giving you legal permission +to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is +no warranty for this free software. For both users' and authors' sake, the GPL +requires that modified versions be marked as changed, so that their problems will not +be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of +the software inside them, although the manufacturer can do so. This is fundamentally +incompatible with the aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we have designed +this version of the GPL to prohibit the practice for those products. If such problems +arise substantially in other domains, we stand ready to extend this provision to +those domains in future versions of the GPL, as needed to protect the freedom of +users. + +Finally, every program is threatened constantly by software patents. States should +not allow patents to restrict development and use of software on general-purpose +computers, but in those that do, we wish to avoid the special danger that patents +applied to a free program could make it effectively proprietary. To prevent this, the +GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions. + +“This License” refers to version 3 of the GNU General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work in +a fashion requiring copyright permission, other than the making of an exact copy. The +resulting work is called a “modified version” of the earlier work or a +work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based on +the Program. + +To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for infringement under +applicable copyright law, except executing it on a computer or modifying a private +copy. Propagation includes copying, distribution (with or without modification), +making available to the public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through a computer +network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” to the +extent that it includes a convenient and prominently visible feature that (1) +displays an appropriate copyright notice, and (2) tells the user that there is no +warranty for the work (except to the extent that warranties are provided), that +licensees may convey the work under this License, and how to view a copy of this +License. If the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code. + +The “source code” for a work means the preferred form of the work for +making modifications to it. “Object code” means any non-source form of a +work. + +A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of interfaces +specified for a particular programming language, one that is widely used among +developers working in that language. + +The “System Libraries” of an executable work include anything, other than +the work as a whole, that (a) is included in the normal form of packaging a Major +Component, but which is not part of that Major Component, and (b) serves only to +enable use of the work with that Major Component, or to implement a Standard +Interface for which an implementation is available to the public in source code form. +A “Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system (if any) on which +the executable work runs, or a compiler used to produce the work, or an object code +interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all the +source code needed to generate, install, and (for an executable work) run the object +code and to modify the work, including scripts to control those activities. However, +it does not include the work's System Libraries, or general-purpose tools or +generally available free programs which are used unmodified in performing those +activities but which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for the work, and +the source code for shared libraries and dynamically linked subprograms that the work +is specifically designed to require, such as by intimate data communication or +control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate +automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +### 2. Basic Permissions. + +All rights granted under this License are granted for the term of copyright on the +Program, and are irrevocable provided the stated conditions are met. This License +explicitly affirms your unlimited permission to run the unmodified Program. The +output from running a covered work is covered by this License only if the output, +given its content, constitutes a covered work. This License acknowledges your rights +of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, without +conditions so long as your license otherwise remains in force. You may convey covered +works to others for the sole purpose of having them make modifications exclusively +for you, or provide you with facilities for running those works, provided that you +comply with the terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for you must do so +exclusively on your behalf, under your direction and control, on terms that prohibit +them from making any copies of your copyrighted material outside their relationship +with you. + +Conveying under any other circumstances is permitted solely under the conditions +stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological measure under any +applicable law fulfilling obligations under article 11 of the WIPO copyright treaty +adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention +of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention of +technological measures to the extent such circumvention is effected by exercising +rights under this License with respect to the covered work, and you disclaim any +intention to limit operation or modification of the work as a means of enforcing, +against the work's users, your or third parties' legal rights to forbid circumvention +of technological measures. + +### 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you receive it, in any +medium, provided that you conspicuously and appropriately publish on each copy an +appropriate copyright notice; keep intact all notices stating that this License and +any non-permissive terms added in accord with section 7 apply to the code; keep +intact all notices of the absence of any warranty; and give all recipients a copy of +this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may offer +support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to produce it from +the Program, in the form of source code under the terms of section 4, provided that +you also meet all of these conditions: + +* **a)** The work must carry prominent notices stating that you modified it, and giving a +relevant date. +* **b)** The work must carry prominent notices stating that it is released under this +License and any conditions added under section 7. This requirement modifies the +requirement in section 4 to “keep intact all notices”. +* **c)** You must license the entire work, as a whole, under this License to anyone who +comes into possession of a copy. This License will therefore apply, along with any +applicable section 7 additional terms, to the whole of the work, and all its parts, +regardless of how they are packaged. This License gives no permission to license the +work in any other way, but it does not invalidate such permission if you have +separately received it. +* **d)** If the work has interactive user interfaces, each must display Appropriate Legal +Notices; however, if the Program has interactive interfaces that do not display +Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, which are +not by their nature extensions of the covered work, and which are not combined with +it such as to form a larger program, in or on a volume of a storage or distribution +medium, is called an “aggregate” if the compilation and its resulting +copyright are not used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work in an aggregate +does not cause this License to apply to the other parts of the aggregate. + +### 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of sections 4 and +5, provided that you also convey the machine-readable Corresponding Source under the +terms of this License, in one of these ways: + +* **a)** Convey the object code in, or embodied in, a physical product (including a +physical distribution medium), accompanied by the Corresponding Source fixed on a +durable physical medium customarily used for software interchange. +* **b)** Convey the object code in, or embodied in, a physical product (including a +physical distribution medium), accompanied by a written offer, valid for at least +three years and valid for as long as you offer spare parts or customer support for +that product model, to give anyone who possesses the object code either (1) a copy of +the Corresponding Source for all the software in the product that is covered by this +License, on a durable physical medium customarily used for software interchange, for +a price no more than your reasonable cost of physically performing this conveying of +source, or (2) access to copy the Corresponding Source from a network server at no +charge. +* **c)** Convey individual copies of the object code with a copy of the written offer to +provide the Corresponding Source. This alternative is allowed only occasionally and +noncommercially, and only if you received the object code with such an offer, in +accord with subsection 6b. +* **d)** Convey the object code by offering access from a designated place (gratis or for +a charge), and offer equivalent access to the Corresponding Source in the same way +through the same place at no further charge. You need not require recipients to copy +the Corresponding Source along with the object code. If the place to copy the object +code is a network server, the Corresponding Source may be on a different server +(operated by you or a third party) that supports equivalent copying facilities, +provided you maintain clear directions next to the object code saying where to find +the Corresponding Source. Regardless of what server hosts the Corresponding Source, +you remain obligated to ensure that it is available for as long as needed to satisfy +these requirements. +* **e)** Convey the object code using peer-to-peer transmission, provided you inform +other peers where the object code and Corresponding Source of the work are being +offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from the +Corresponding Source as a System Library, need not be included in conveying the +object code work. + +A “User Product” is either (1) a “consumer product”, which +means any tangible personal property which is normally used for personal, family, or +household purposes, or (2) anything designed or sold for incorporation into a +dwelling. In determining whether a product is a consumer product, doubtful cases +shall be resolved in favor of coverage. For a particular product received by a +particular user, “normally used” refers to a typical or common use of +that class of product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected to use, the +product. A product is a consumer product regardless of whether the product has +substantial commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install and execute +modified versions of a covered work in that User Product from a modified version of +its Corresponding Source. The information must suffice to ensure that the continued +functioning of the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for +use in, a User Product, and the conveying occurs as part of a transaction in which +the right of possession and use of the User Product is transferred to the recipient +in perpetuity or for a fixed term (regardless of how the transaction is +characterized), the Corresponding Source conveyed under this section must be +accompanied by the Installation Information. But this requirement does not apply if +neither you nor any third party retains the ability to install modified object code +on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to +continue to provide support service, warranty, or updates for a work that has been +modified or installed by the recipient, or for the User Product in which it has been +modified or installed. Access to a network may be denied when the modification itself +materially and adversely affects the operation of the network or violates the rules +and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with +this section must be in a format that is publicly documented (and with an +implementation available to the public in source code form), and must require no +special password or key for unpacking, reading or copying. + +### 7. Additional Terms. + +“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. Additional +permissions that are applicable to the entire Program shall be treated as though they +were included in this License, to the extent that they are valid under applicable +law. If additional permissions apply only to part of the Program, that part may be +used separately under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any +additional permissions from that copy, or from any part of it. (Additional +permissions may be written to require their own removal in certain cases when you +modify the work.) You may place additional permissions on material, added by you to a +covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a +covered work, you may (if authorized by the copyright holders of that material) +supplement the terms of this License with terms: + +* **a)** Disclaiming warranty or limiting liability differently from the terms of +sections 15 and 16 of this License; or +* **b)** Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices displayed by works +containing it; or +* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that +modified versions of such material be marked in reasonable ways as different from the +original version; or +* **d)** Limiting the use for publicity purposes of names of licensors or authors of the +material; or +* **e)** Declining to grant rights under trademark law for use of some trade names, +trademarks, or service marks; or +* **f)** Requiring indemnification of licensors and authors of that material by anyone +who conveys the material (or modified versions of it) with contractual assumptions of +liability to the recipient, for any liability that these contractual assumptions +directly impose on those licensors and authors. + +All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you received +it, or any part of it, contains a notice stating that it is governed by this License +along with a term that is a further restriction, you may remove that term. If a +license document contains a further restriction but permits relicensing or conveying +under this License, you may add to a covered work material governed by the terms of +that license document, provided that the further restriction does not survive such +relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in +the relevant source files, a statement of the additional terms that apply to those +files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a +separately written license, or stated as exceptions; the above requirements apply +either way. + +### 8. Termination. + +You may not propagate or modify a covered work except as expressly provided under +this License. Any attempt otherwise to propagate or modify it is void, and will +automatically terminate your rights under this License (including any patent licenses +granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a +particular copyright holder is reinstated (a) provisionally, unless and until the +copyright holder explicitly and finally terminates your license, and (b) permanently, +if the copyright holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently +if the copyright holder notifies you of the violation by some reasonable means, this +is the first time you have received notice of violation of this License (for any +work) from that copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of +parties who have received copies or rights from you under this License. If your +rights have been terminated and not permanently reinstated, you do not qualify to +receive new licenses for the same material under section 10. + +### 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run a copy of the +Program. Ancillary propagation of a covered work occurring solely as a consequence of +using peer-to-peer transmission to receive a copy likewise does not require +acceptance. However, nothing other than this License grants you permission to +propagate or modify any covered work. These actions infringe copyright if you do not +accept this License. Therefore, by modifying or propagating a covered work, you +indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically receives a license +from the original licensors, to run, modify and propagate that work, subject to this +License. You are not responsible for enforcing compliance by third parties with this +License. + +An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an organization, or +merging organizations. If propagation of a covered work results from an entity +transaction, each party to that transaction who receives a copy of the work also +receives whatever licenses to the work the party's predecessor in interest had or +could give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if the predecessor +has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or +affirmed under this License. For example, you may not impose a license fee, royalty, +or other charge for exercise of rights granted under this License, and you may not +initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging +that any patent claim is infringed by making, using, selling, offering for sale, or +importing the Program or any portion of it. + +### 11. Patents. + +A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The work thus +licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims owned or +controlled by the contributor, whether already acquired or hereafter acquired, that +would be infringed by some manner, permitted by this License, of making, using, or +selling its contributor version, but do not include claims that would be infringed +only as a consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant patent +sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license +under the contributor's essential patent claims, to make, use, sell, offer for sale, +import and otherwise run, modify and propagate the contents of its contributor +version. + +In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent (such as an +express permission to practice a patent or covenant not to sue for patent +infringement). To “grant” such a patent license to a party means to make +such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the +Corresponding Source of the work is not available for anyone to copy, free of charge +and under the terms of this License, through a publicly available network server or +other readily accessible means, then you must either (1) cause the Corresponding +Source to be so available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner consistent with +the requirements of this License, to extend the patent license to downstream +recipients. “Knowingly relying” means you have actual knowledge that, but +for the patent license, your conveying the covered work in a country, or your +recipient's use of the covered work in a country, would infringe one or more +identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you +convey, or propagate by procuring conveyance of, a covered work, and grant a patent +license to some of the parties receiving the covered work authorizing them to use, +propagate, modify or convey a specific copy of the covered work, then the patent +license you grant is automatically extended to all recipients of the covered work and +works based on it. + +A patent license is “discriminatory” if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on the +non-exercise of one or more of the rights that are specifically granted under this +License. You may not convey a covered work if you are a party to an arrangement with +a third party that is in the business of distributing software, under which you make +payment to the third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties who would receive +the covered work from you, a discriminatory patent license (a) in connection with +copies of the covered work conveyed by you (or copies made from those copies), or (b) +primarily for and in connection with specific products or compilations that contain +the covered work, unless you entered into that arrangement, or that patent license +was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied +license or other defenses to infringement that may otherwise be available to you +under applicable patent law. + +### 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or otherwise) +that contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot convey a covered work so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not convey it at all. For example, if you +agree to terms that obligate you to collect a royalty for further conveying from +those to whom you convey the Program, the only way you could satisfy both those terms +and this License would be to refrain entirely from conveying the Program. + +### 13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have permission to link or +combine any covered work with a work licensed under version 3 of the GNU Affero +General Public License into a single combined work, and to convey the resulting work. +The terms of this License will continue to apply to the part which is the covered +work, but the special requirements of the GNU Affero General Public License, section +13, concerning interaction through a network will apply to the combination as such. + +### 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of the GNU +General Public License from time to time. Such new versions will be similar in spirit +to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies that +a certain numbered version of the GNU General Public License “or any later +version” applies to it, you have the option of following the terms and +conditions either of that numbered version or of any later version published by the +Free Software Foundation. If the Program does not specify a version number of the GNU +General Public License, you may choose any version ever published by the Free +Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the GNU +General Public License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no +additional obligations are imposed on any author or copyright holder as a result of +your choosing to follow a later version. + +### 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE +QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +### 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY +COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS +PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE +OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE +WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided above cannot be +given local legal effect according to their terms, reviewing courts shall apply local +law that most closely approximates an absolute waiver of all civil liability in +connection with the Program, unless a warranty or assumption of liability accompanies +a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +## How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to +the public, the best way to achieve this is to make it free software which everyone +can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them +to the start of each source file to most effectively state the exclusion of warranty; +and each file should have at least the “copyright” line and a pointer to +where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this +when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate parts of +the General Public License. Of course, your program's commands might be different; +for a GUI interface, you would use an “about box”. + +You should also get your employer (if you work as a programmer) or school, if any, to +sign a “copyright disclaimer” for the program, if necessary. For more +information on this, and how to apply and follow the GNU GPL, see +<<http://www.gnu.org/licenses/>>. + +The GNU General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may consider it +more useful to permit linking proprietary applications with the library. If this is +what you want to do, use the GNU Lesser General Public License instead of this +License. But first, please read +<<http://www.gnu.org/philosophy/why-not-lgpl.html>>. diff --git a/README b/README deleted file mode 100644 index be6200ead..000000000 --- a/README +++ /dev/null @@ -1,88 +0,0 @@ -Description -=========== - -pyLoad is a free and open source downloader for 1-click-hosting sites -like rapidshare.com or uploaded.to. -It supports link decryption as well as all important container formats. - -pyLoad is written entirely in Python and is currently under heavy development. - -For news, downloads, wiki, forum and further information visit http://pyload.org/ - -To report bugs, suggest features, ask a question, get the developer version -or help us out, visit http://github.com/pyload/pyload - -Documentation about extending pyLoad can be found at http://docs.pyload.org or join us at #pyload on irc.freenode.net - -Dependencies -============ - -You need at least python 2.5 to run pyLoad and all of these required libaries. -They should be automatically installed when using pip install. -The prebuilt pyload packages also install these dependencies or have them included, so manuall install -is only needed when installing pyLoad from source. - -Required --------- - -- pycurl a.k.a python-curl -- jinja2 -- beaker -- thrift -- simplejson (for python 2.5) - -Some plugins require additional packages, only install these when needed. - -Optional --------- - -- pycrypto: RSDF/CCF/DLC support -- tesseract, python-pil a.k.a python-imaging: Automatic captcha recognition for a small amount of plugins -- jsengine (spidermonkey, ossp-js, pyv8, rhino): Used for several hoster, ClickNLoad -- feedparser -- BeautifulSoup -- pyOpenSSL: For SSL connection - -First start -=========== - -Note: If you installed pyload via package-manager `python pyLoadCore.py` is probably equivalent to `pyLoadCore` - -Run:: - - python pyLoadCore.py - -and follow the instructions of the setup assistent. - -For a list of options use:: - - python pyLoadCore.py -h - -Configuration -============= - -After finishing the setup assistent pyLoad is ready to use and more configuration can be done via webinterface. -Additionally you could simply edit the config files located in your pyLoad home dir (defaults to: ~/.pyload) -with your favorite editor and edit the appropriate options. For a short description of -the options take a look at http://pyload.org/configuration. - -To restart the configure assistent run:: - - python pyLoadCore.py -s - -Adding downloads ----------------- - -To start the CLI and connect to a local server, run:: - - python pyLoadCli.py -l - -for more options refer to:: - - python pyLoadCli.py -h - -The webinterface can be accessed when pointing your webbrowser to the ip and configured port, defaults to http://localhost:8000 - -Notes -===== -For more information, see http://pyload.org/ diff --git a/README.md b/README.md new file mode 100644 index 000000000..c0ddbc416 --- /dev/null +++ b/README.md @@ -0,0 +1,139 @@ +[](http://pyload.org/) +==================================================================== + +[](http://translate.pyload.org/project/pyload/) + +**pyLoad** is a Free and Open Source download manager written entirely in Python and designed to be extremely lightweight. + +pyLoad is available for all kind of operating systems and devices: +You could install it on a computer, but also on a headless servers, a router, a smart usb-stick running linux... almost whatever you want! + +You can control it entirely by web. +Its web user interface allows full managing and easily remote access to your download from anywhere, online, or in your personal network.. + +All common video-sites, one-click-hosters, container formats and well known web standards are supported to allow you to download files. +Additionaly, pyLoad has a great variety of plugins to automate common tasks and make unattended running possible. + +pyLoad has a fully featured and well documented API, it's easily extendable and accessible by external tools, cross-platform apps or other softwares. + + +Dependencies +------------ + + - **You need at least Python 2.5 or at most Python 2.7 to run pyLoad and its required software libraries** + - **Python 3 and PyPy are not yet supported** + +### Required ### + + - **Beaker** + - **bottle** + - **Getch** + - **jinja2** + - **markupsafe** + - **MultipartPostHandler** + - **pycurl** (python-curl) + - **rename_process** + - **SafeEval** + - **simplejson** *required for JSON speedup* + - **thrift** + - **wsgiserver** + +Some addition features require additional packages. + + +### Optional ### + + - **BeautifulSoup** + - **bjoern** (<https://github.com/jonashaag/bjoern>) *required for a better webui experience* + - **feedparser** *required for RSS parsing support* + - **node.js** or **ossp-js** or **pyv8** or **rhino** or **spidermonkey** (JS Engines) *required by plugins like ClickNLoad to work correctly* + - **PIL** (python-imaging) *required for captcha recognition support* + - **pycrypto** *required for RSDF/CCF/DLC container decrypting* + - **pyOpenSSL** *required for SSL connection support* + - **tesseract** *required for captcha ocr support* + +You can install them using the Python Package Index: + + pip install <package-name> + + +### Included ### + + - **Beaker** + - **BeautifulSoup** + - **bottle** + - **feedparser** + - **Getch** + - **jinja2** + - **markupsafe** + - **MultipartPostHandler** + - **rename_process** + - **SafeEval** + - **simplejson** + - **thrift** + - **wsgiserver** + +> **Note:** +Pre-build packages should yet include all. + + +Usage +----- + +### First start ### + +Run: + + python pyload.py + +and follow the setup assistant instructions. + +> **Note:** +If you installed pyLoad by package-manager, command `python pyload.py` is probably equivalent to `pyload`. + +Additionally, you can whenever restart the setup assistant typing: + + python pyload.py -s + +Or you can even edit configuration files located in your pyLoad home directory (default to `~/.pyload`) +with your favorite editor. +For a short description of all the configuration options available visit <http://pyload.org/configuration>. + + +### Web User Interface ### + +Run: + + python pyload.py + +So, to retrieve it point your web browser to the socket address configured by setup (default to `http://localhost:8000`). + +You can get the list of accepted arguments typing: + + python pyload.py -h + + +### Command Line Interface ### + +Run: + + python pyload-cli.py -l + +You can get the list of accepted arguments typing: + + python pyload-cli.py -h + + +Notes +----- + +For news, downloads, wiki, forum and further information visit <http://pyload.org/>. + +To report bugs, suggest features, ask a question, get the developer version +or help us out, visit <https://github.com/pyload/pyload>. + +Documentation about extending pyLoad can be found at <http://docs.pyload.org> or joining us at `#pyload` on `irc.freenode.net`. + + +------------------------------ +###### pyLoad Team 2008-2014 ###### diff --git a/docs/access_api.rst b/docs/access_api.rst index df69da8b2..ce78364b9 100644 --- a/docs/access_api.rst +++ b/docs/access_api.rst @@ -118,4 +118,4 @@ Strings are wrapped in double qoutes, because `"username"` represents a string i every container type like lists and dicts are possible. You usually don't have to convert them. just use a json encoder before using them in the HTTP request. -Please note that the data have to be urlencoded at last. (Most libaries will do that automatically)
\ No newline at end of file +Please note that the data have to be urlencoded at last. (Most libaries will do that automatically) diff --git a/docs/conf.py b/docs/conf.py index 9d2cf98f9..b5976d2fc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -52,7 +52,7 @@ master_doc = 'index' # General information about the project. project = u'pyLoad' -copyright = u'2011, pyLoad Team' +copyright = u'2008-2014, pyLoad Team' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -66,7 +66,7 @@ cog.outl("version = '%s'" % ".".join(v[:2])) cog.outl("release = '%s'" % ".".join(v)) ]]]""" version = '0.4' -release = '0.4.9' +release = '0.4.10' # [[[end]]] @@ -133,7 +133,7 @@ html_logo = join(dir_name, "module", "web", "media", "default", "img", "pyload-l # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = join(dir_name, "icons", "pyload2.ico") +html_favicon = join(dir_name, "docs", "resources", "icon.ico") # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/docs.conf b/docs/docs.conf index e197cfa43..0f30ab89e 100644 --- a/docs/docs.conf +++ b/docs/docs.conf @@ -3,12 +3,12 @@ [epydoc] -modules: pyLoadCore.py, pyLoadCli.py, pyloadGui.py, module +modules: pyload.py, pyload-cli.py, module output: html target: docs docformat: restructuredtext -exclude: module\.lib|module\.remote\.thriftbackend\.thriftgen|PyQt4|\.pyc|\.pyo|module\.plugins\.(accounts|captcha|container|crypter|hooks|hoster) +exclude: module\.lib|module\.remote\.thriftbackend\.thriftgen|\.pyc|\.pyo|module\.plugins\.(accounts|container|crypter|hooks|hoster|internal|ocr) name: pyLoad Documentation url: http://docs.pyload.org diff --git a/docs/extend_pyload.rst b/docs/extend_pyload.rst index 337cb6854..e8b60b63c 100755 --- a/docs/extend_pyload.rst +++ b/docs/extend_pyload.rst @@ -10,4 +10,4 @@ every detail of the pyLoad core. However you should have some basic knowledge of .. toctree:: write_hooks.rst - write_plugins.rst
\ No newline at end of file + write_plugins.rst diff --git a/docs/resources/banner.png b/docs/resources/banner.png Binary files differnew file mode 100644 index 000000000..4e2d718f7 --- /dev/null +++ b/docs/resources/banner.png diff --git a/docs/resources/icon.ico b/docs/resources/icon.ico Binary files differnew file mode 100644 index 000000000..b5fb55686 --- /dev/null +++ b/docs/resources/icon.ico diff --git a/docs/resources/logo.png b/docs/resources/logo.png Binary files differnew file mode 100644 index 000000000..d20084847 --- /dev/null +++ b/docs/resources/logo.png diff --git a/docs/resources/logo.svg b/docs/resources/logo.svg new file mode 100644 index 000000000..f67815678 --- /dev/null +++ b/docs/resources/logo.svg @@ -0,0 +1,317 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:version="0.32"
+ sodipodi:docname="pyload_logo.svg"
+ x="0px"
+ y="0px"
+ width="1000"
+ height="1000"
+ viewBox="0 0 1000 1000"
+ enable-background="new 0 0 1000 1000"
+ xml:space="preserve"
+ inkscape:export-filename="/Users/christian/Development/pyload/docs/resources/pyload_logo.png"
+ inkscape:export-xdpi="9.2647057"
+ inkscape:export-ydpi="9.2647057"><title
+ id="title3794">pyLoad Logo</title><metadata
+ id="metadata33"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>pyLoad Logo</dc:title><dc:creator><cc:Agent><dc:title>pyLoad Team</dc:title></cc:Agent></dc:creator><cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /><dc:subject><rdf:Bag><rdf:li>pyload logo</rdf:li></rdf:Bag></dc:subject><dc:description>Official pyLoad logo with some optional filters</dc:description></cc:Work><cc:License
+ rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"><cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:requires
+ rdf:resource="http://creativecommons.org/ns#Notice" /><cc:requires
+ rdf:resource="http://creativecommons.org/ns#Attribution" /><cc:prohibits
+ rdf:resource="http://creativecommons.org/ns#CommercialUse" /><cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><cc:requires
+ rdf:resource="http://creativecommons.org/ns#ShareAlike" /></cc:License></rdf:RDF></metadata><defs
+ id="defs31"><color-profile
+ name="Generic-RGB-Profile"
+ xlink:href="/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"
+ id="color-profile3792" /><linearGradient
+ gradientTransform="matrix(0.5625,0,0,-0.568,125.7979,708.7776)"
+ y2="752.55798"
+ x2="783.30792"
+ y1="134.5405"
+ x1="1220.123"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3778">
+ <stop
+ id="stop3780"
+ style="stop-color:#ffd856;stop-opacity:1;"
+ offset="0" />
+ <stop
+ id="stop3782"
+ style="stop-color:#ffc836;stop-opacity:1;"
+ offset="1" />
+ </linearGradient><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3778"
+ id="linearGradient3005"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0266298,0,0,1,-7.2192914,0)"
+ spreadMethod="pad"
+ x1="271.09799"
+ y1="499.06601"
+ x2="1001.7615"
+ y2="499.06601" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#path1948_3_"
+ id="linearGradient3783"
+ x1="25.991835"
+ y1="239.76074"
+ x2="763.24133"
+ y2="239.76074"
+ gradientUnits="userSpaceOnUse" /><filter
+ id="filter3020"
+ inkscape:label="Drop shadow"
+ width="1.5"
+ height="1.5"
+ x="-.25"
+ y="-.25"><feGaussianBlur
+ id="feGaussianBlur3022"
+ in="SourceAlpha"
+ stdDeviation="25"
+ result="blur" /><feColorMatrix
+ id="feColorMatrix3024"
+ result="bluralpha"
+ type="matrix"
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " /><feOffset
+ id="feOffset3026"
+ in="bluralpha"
+ dx="15"
+ dy="30"
+ result="offsetBlur" /><feMerge
+ id="feMerge3028"><feMergeNode
+ id="feMergeNode3030"
+ in="offsetBlur" /><feMergeNode
+ id="feMergeNode3032"
+ in="SourceGraphic" /></feMerge></filter><filter
+ id="filter3023"
+ inkscape:label="Outline"
+ inkscape:menu="Morphology"
+ inkscape:menu-tooltip="Draws a colored outline around"
+ width="1.5"
+ height="1.5"
+ x="-0.25"
+ y="-0.25"
+ color-interpolation-filters="sRGB"><feGaussianBlur
+ id="feGaussianBlur3025"
+ in="SourceAlpha"
+ stdDeviation="10"
+ result="blur" /><feColorMatrix
+ id="feColorMatrix3027"
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 100 -1 "
+ result="result4" /><feFlood
+ id="feFlood3029"
+ result="result1"
+ flood-color="rgb(0,0,0)"
+ in="blur"
+ flood-opacity="1" /><feComposite
+ id="feComposite3031"
+ in2="result4"
+ result="result2"
+ in="result1"
+ operator="atop" /><feComposite
+ id="feComposite3033"
+ in2="result2"
+ in="SourceGraphic"
+ result="result3"
+ operator="atop" /></filter><filter
+ id="filter3140"
+ inkscape:label="3D Effect"
+ inkscape:menu="Bevels"
+ inkscape:menu-tooltip="Basic specular bevel to use for building textures"
+ color-interpolation-filters="sRGB"><feGaussianBlur
+ id="feGaussianBlur3142"
+ stdDeviation="6"
+ in="SourceGraphic"
+ result="result0" /><feDiffuseLighting
+ id="feDiffuseLighting3144"
+ lighting-color="rgb(255,255,255)"
+ diffuseConstant="1"
+ surfaceScale="4"
+ result="result5"><feDistantLight
+ id="feDistantLight3146"
+ elevation="45"
+ azimuth="235" /></feDiffuseLighting><feComposite
+ id="feComposite3148"
+ in2="SourceGraphic"
+ k1="1.4"
+ in="result5"
+ result="fbSourceGraphic"
+ operator="arithmetic" /><feGaussianBlur
+ id="feGaussianBlur3150"
+ result="result0"
+ in="fbSourceGraphic"
+ stdDeviation="6" /><feSpecularLighting
+ id="feSpecularLighting3152"
+ specularExponent="25"
+ specularConstant="1"
+ surfaceScale="4"
+ lighting-color="rgb(255,255,255)"
+ result="result1"
+ in="result0"><feDistantLight
+ id="feDistantLight3154"
+ azimuth="235"
+ elevation="45" /></feSpecularLighting><feComposite
+ id="feComposite3156"
+ in2="result91"
+ k3="1"
+ k2="1"
+ operator="arithmetic"
+ result="result4"
+ in="fbSourceGraphic" /><feComposite
+ id="feComposite3158"
+ in2="SourceGraphic"
+ operator="in"
+ result="result2"
+ in="result4" /></filter></defs><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1352"
+ inkscape:window-height="766"
+ id="namedview29"
+ showgrid="false"
+ inkscape:zoom="0.5"
+ inkscape:cx="556.17192"
+ inkscape:cy="487.74566"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="g2303_1_"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ showborder="true"
+ borderlayer="false"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+<g
+ id="g2303"
+ display="none"
+ style="display:none"
+ transform="translate(-21.799529,1.0000288)">
+
+ <linearGradient
+ id="path1948_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="-338.45169"
+ y1="1559.3135"
+ x2="627.55139"
+ y2="728.19678"
+ gradientTransform="matrix(0.5625,0,0,-0.568,125.7979,708.7776)">
+ <stop
+ offset="0"
+ style="stop-color:#5A9FD4"
+ id="stop5" />
+ <stop
+ offset="1"
+ style="stop-color:#306998"
+ id="stop7" />
+ </linearGradient>
+ <path
+ id="path1948"
+ display="inline"
+ d="M 493.674,-0.868 H 256.098 166.937 c -69.042,0 -129.5,41.498 -148.412,120.447 -21.813,90.495 -22.783,146.964 0,241.457 16.887,70.339 57.219,120.447 126.26,120.447 h 81.686 V 372.939 c 0,-78.413 67.856,-147.585 148.416,-147.585 h 237.298 c 66.057,0 118.787,-54.385 118.787,-120.727 L 730.846,-0.89"
+ inkscape:connector-curvature="0"
+ style="fill:url(#path1948_2_);display:inline" />
+
+ <linearGradient
+ id="path1950_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="1186.2559"
+ y1="133.9731"
+ x2="749.44067"
+ y2="751.99072"
+ gradientTransform="matrix(0.5625,0,0,-0.568,125.7979,708.7776)">
+ <stop
+ offset="0"
+ style="stop-color:#FFD43B"
+ id="stop11" />
+ <stop
+ offset="1"
+ style="stop-color:#FFE873"
+ id="stop13" />
+ </linearGradient>
+ <path
+ id="path1950"
+ display="inline"
+ d="m 755.602,0.132 v 105.496 c 0,81.799 -69.346,150.631 -148.418,150.631 H 369.886 c -65.002,0 -118.788,55.632 -118.788,120.727 v 226.221 c 0,64.39 55.985,102.262 118.788,120.727 C 412.959,736.601 500,1000 500,1000 c 0,0 68.736,-264.907 107.184,-276.066 59.809,-17.313 118.787,-52.168 118.787,-120.727 V 512.666 H 488.673 V 482.483 H 725.97 844.761 c 69.049,0 94.783,-48.163 118.787,-120.447 24.809,-74.417 23.752,-145.985 0,-241.457 C 946.486,51.85 913.898,0.132 844.762,0.132 h -89.16 z M 622.137,573.026 c 24.627,0 44.578,20.179 44.578,45.137 0,25.041 -19.951,45.409 -44.578,45.409 -24.541,0 -44.58,-20.368 -44.58,-45.409 0,-24.958 20.039,-45.137 44.58,-45.137 z"
+ inkscape:connector-curvature="0"
+ style="fill:url(#path1950_2_);display:inline" />
+</g>
+<g
+ id="g2303_1_"
+ transform="translate(-21.799529,1.0000288)">
+
+ <linearGradient
+ id="path1948_3_"
+ gradientUnits="userSpaceOnUse"
+ x1="-303.33109"
+ y1="1560.5684"
+ x2="662.672"
+ y2="729.45172"
+ gradientTransform="matrix(0.57252813,0,0,-0.568,127.65196,708.7776)">
+ <stop
+ offset="0"
+ style="stop-color:#3778b0;stop-opacity:1;"
+ id="stop18" />
+ <stop
+ offset="1"
+ style="stop-color:#356b97;stop-opacity:1;"
+ id="stop20" />
+ </linearGradient>
+ <path
+ style="fill:url(#linearGradient3783);fill-opacity:1;"
+ d="M 187.6338,-0.828786 C 142.54691,-0.4970408 97.509189,20.00164 69.766894,55.506872 50.404869,79.267481 40.287236,108.86774 34.426911,138.63795 22.416163,189.64033 17.78885,242.92961 25.780677,294.93728 c 5.106096,32.23417 11.057028,64.60794 22.392916,95.27781 13.479342,35.90012 38.974607,69.46226 76.144837,82.91501 27.93718,10.93473 54.60541,6.72414 83.9641,7.53695 13.63487,0 24.96913,0 38.604,0 0.2713,-39.75457 -0.23921,-79.53817 0.7,-119.27522 4.44911,-60.56565 57.97765,-113.83582 116.49553,-129.10577 28.59598,-7.98504 58.75298,-3.97369 88.12613,-4.95196 65.78932,-0.1699 131.59413,0.33658 197.37399,-0.24727 46.56452,-2.36951 89.41253,-33.74388 105.96031,-76.7788 8.4927,-20.25194 9.04154,-42.50123 8.36849,-64.136866 -0.0327,-28.519022 -0.0719,-58.538168 -0.10062,-87.0571928 -160.2708,-0.8222611 -320.54247,-0.1692627 -480.8154,0.027 -31.78694,0.021047 -63.57472,-0.0424765 -95.36116,0.0302428 z"
+ id="path1948_1_"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccc" />
+
+ <linearGradient
+ id="path1950_3_"
+ gradientUnits="userSpaceOnUse"
+ x1="1220.123"
+ y1="134.5405"
+ x2="783.30792"
+ y2="752.55798"
+ gradientTransform="matrix(0.5625,0,0,-0.568,125.7979,708.7776)"
+ xlink:href="#linearGradient3778">
+ <stop
+ offset="0"
+ style="stop-color:#fae13f;stop-opacity:1;"
+ id="stop24" />
+ <stop
+ offset="1"
+ style="stop-color:#facc2b;stop-opacity:1;"
+ id="stop26" />
+ </linearGradient>
+ <path
+ id="path1950_1_"
+ d="m 789.03685,-0.868 v 105.496 c 0,81.799 -71.19267,150.631 -152.37034,150.631 H 393.0493 c -66.73298,0 -121.9513,55.632 -121.9513,120.727 v 226.221 c 0,64.39 255.53022,396.793 255.53022,396.793 0,0 231.98858,-328.234 231.98858,-396.793 V 511.666 H 515.00061 V 481.483 H 758.6168 880.57116 c 70.88777,0 97.30706,-48.163 121.95034,-120.447 25.4697,-74.417 24.3844,-145.985 0,-241.457 C 985.00406,50.85 951.54825,-0.868 880.57116,-0.868 H 789.03685 z M 652.0177,572.026 c 25.28282,0 45.76511,20.179 45.76511,45.137 0,25.041 -20.48229,45.409 -45.76511,45.409 -25.19452,0 -45.76716,-20.368 -45.76716,-45.409 0,-24.958 20.57264,-45.137 45.76716,-45.137 z"
+ style="fill:url(#linearGradient3005);fill-opacity:1;"
+ inkscape:connector-curvature="0" />
+</g>
+</svg>
\ No newline at end of file diff --git a/docs/write_hooks.rst b/docs/write_hooks.rst index dd60367b7..a088a3ed3 100644 --- a/docs/write_hooks.rst +++ b/docs/write_hooks.rst @@ -23,10 +23,9 @@ All Hooks should start with something like this: :: __version__ = "0.1" __description__ = "Does really cool stuff" __config__ = [ ("activated" , "bool" , "Activated" , "True" ) ] - __threaded__ = ["downloadFinished"] __author_name__ = ("Me") __author_mail__ = ("me@has-no-mail.com") - + All meta-data is defined in the header, you need at least one option at ``__config__`` so the user can toggle your hook on and off. Dont't overwrite the ``init`` method if not neccesary, use ``setup`` instead. @@ -35,7 +34,7 @@ Using the Config We are taking a closer look at the ``__config__`` parameter. You can add more config values as desired by adding tuples of the following format to the config list: ``("name", "type", "description", "default value")``. -When everything went right you can access the config values with ``self.getConfig(name)`` and ``self.setConfig(name,value``. +When everything went right you can access the config values with ``self.getConfig(name)`` and ``self.setConfig(name, value``. Interacting on Events @@ -65,9 +64,6 @@ A basic excerpt would look like: :: def downloadFinished(self, pyfile): print "A Download just finished." -Another important feature to mention can be seen at the ``__threaded__`` parameter. Function names listed will be executed -in a thread, in order to not block the main thread. This should be used for all kind of longer processing tasks. - Another and more flexible and powerful way is to use event listener. All hook methods exists as event and very useful additional events are dispatched by the core. For a little overview look at :class:`HookManager <module.HookManager.HookManager>`. Keep in mind that you can define own events and other people may listen on them. @@ -81,7 +77,7 @@ It requires a `dict` that maps event names to function names or a `list` of func """ Your Hook code here. """ - event_map = {"downloadFinished" : "doSomeWork", + event_map = {"downloadFinished": "doSomeWork", "allDownloadsFnished": "someMethod", "coreReady": "initialize"} @@ -117,7 +113,7 @@ Sounds complicated but is very easy to do. Just use the ``Expose`` decorator: :: """ Your Hook code here. """ - + @Expose def invoke(self, arg): print "Invoked with", arg @@ -158,5 +154,5 @@ Usable with: :: Example ------- Sorry but you won't find an example here ;-) - + Look at :file:`module/plugins/hooks` and you will find plenty examples there. diff --git a/docs/write_plugins.rst b/docs/write_plugins.rst index b513a5978..ff3be66d0 100644 --- a/docs/write_plugins.rst +++ b/docs/write_plugins.rst @@ -47,7 +47,7 @@ An example ``process`` function could look like this :: """ plugin code """ - + def process(self, pyfile): html = self.load(pyfile.url) # load the content of the orginal pyfile.url to html @@ -100,4 +100,4 @@ where urls is the list of urls contained in the packages. Thats all of your work Examples -------- -Best examples are already existing plugins in :file:`module/plugins/`.
\ No newline at end of file +Best examples are already existing plugins in :file:`module/plugins/`. diff --git a/icons/abort.png b/icons/abort.png Binary files differdeleted file mode 100644 index 66170aae7..000000000 --- a/icons/abort.png +++ /dev/null diff --git a/icons/clipboard.png b/icons/clipboard.png Binary files differdeleted file mode 100644 index 9ba608eba..000000000 --- a/icons/clipboard.png +++ /dev/null diff --git a/icons/close.png b/icons/close.png Binary files differdeleted file mode 100644 index 66170aae7..000000000 --- a/icons/close.png +++ /dev/null diff --git a/icons/edit_small.png b/icons/edit_small.png Binary files differdeleted file mode 100644 index eb76e21b4..000000000 --- a/icons/edit_small.png +++ /dev/null diff --git a/icons/logo-gui.png b/icons/logo-gui.png Binary files differdeleted file mode 100644 index 5994b274d..000000000 --- a/icons/logo-gui.png +++ /dev/null diff --git a/icons/logo.png b/icons/logo.png Binary files differdeleted file mode 100644 index 72a95b740..000000000 --- a/icons/logo.png +++ /dev/null diff --git a/icons/pull_small.png b/icons/pull_small.png Binary files differdeleted file mode 100644 index 432ad321f..000000000 --- a/icons/pull_small.png +++ /dev/null diff --git a/icons/push_small.png b/icons/push_small.png Binary files differdeleted file mode 100644 index 701fc69e3..000000000 --- a/icons/push_small.png +++ /dev/null diff --git a/icons/pyload-gui.ico b/icons/pyload-gui.ico Binary files differdeleted file mode 100644 index 00a1a53ff..000000000 --- a/icons/pyload-gui.ico +++ /dev/null diff --git a/icons/pyload.ico b/icons/pyload.ico Binary files differdeleted file mode 100644 index 58b1f4b89..000000000 --- a/icons/pyload.ico +++ /dev/null diff --git a/icons/pyload2.ico b/icons/pyload2.ico Binary files differdeleted file mode 100644 index c2b497986..000000000 --- a/icons/pyload2.ico +++ /dev/null diff --git a/icons/refresh1_small.png b/icons/refresh1_small.png Binary files differdeleted file mode 100644 index ce4f24efc..000000000 --- a/icons/refresh1_small.png +++ /dev/null diff --git a/icons/refresh_small.png b/icons/refresh_small.png Binary files differdeleted file mode 100644 index 1ffd18d97..000000000 --- a/icons/refresh_small.png +++ /dev/null diff --git a/icons/remove_small.png b/icons/remove_small.png Binary files differdeleted file mode 100644 index bf99763e8..000000000 --- a/icons/remove_small.png +++ /dev/null diff --git a/icons/toolbar_add.png b/icons/toolbar_add.png Binary files differdeleted file mode 100644 index 17003e9f0..000000000 --- a/icons/toolbar_add.png +++ /dev/null diff --git a/icons/toolbar_pause.png b/icons/toolbar_pause.png Binary files differdeleted file mode 100644 index b7a727b71..000000000 --- a/icons/toolbar_pause.png +++ /dev/null diff --git a/icons/toolbar_remove.png b/icons/toolbar_remove.png Binary files differdeleted file mode 100644 index 1e9c00e16..000000000 --- a/icons/toolbar_remove.png +++ /dev/null diff --git a/icons/toolbar_start.png b/icons/toolbar_start.png Binary files differdeleted file mode 100644 index 1123266e6..000000000 --- a/icons/toolbar_start.png +++ /dev/null diff --git a/icons/toolbar_stop.png b/icons/toolbar_stop.png Binary files differdeleted file mode 100644 index b388e3d72..000000000 --- a/icons/toolbar_stop.png +++ /dev/null diff --git a/locale/README.md b/locale/README.md new file mode 100644 index 000000000..2751611f7 --- /dev/null +++ b/locale/README.md @@ -0,0 +1,55 @@ +# Localization [](http://translate.pyload.org/project/pyload) + +The localization process take place on Crowdin: + +http://translate.pyload.org + +or + +http://crowdin.net/project/pyload + +## Add a tip for translators +If you want to explain a translatable string to make the translation process easier you can do that using comment block starting with `L10N:`. For example: + +```python +# L10N: Here the tip for translators +# Thanks +print _("A translatable string") +``` + +Translators will see: + +``` +L10N: Here the tip for translators +Thanks +``` + +## Updating templates + +To update POT files run: + +`paver generate_locale` + +to automatically upload the updated POTs on Crowdin for the localization process just run: + +`paver upload_translations -k [api_key]` + +the API Key can be retrieved in the Settings panel of the project on Crowdin. This is allowed only to administrators. + +## Retrieve updated PO files + +Updated PO files can be automatically download from Crowdin using: + +`paver download_translations -k [api_key]` + +This is allowed only to administrators, users can download the last version of the translations using the Crowdin web interface. + +## Compile PO files + +MO files can be generated using: + +`paver compile_translations` + +To compile a single file just use `msgfmt`. For example to compile a core.po file run: + +`msgfmt -o core.mo core.po` diff --git a/locale/af/LC_MESSAGES/django.po b/locale/af/LC_MESSAGES/django.po new file mode 100644 index 000000000..f847c8fcf --- /dev/null +++ b/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Afrikaans\n" +"Language: af_ZA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/af/LC_MESSAGES/pyLoad.po b/locale/af/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..ae1eec95b --- /dev/null +++ b/locale/af/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Afrikaans\n" +"Language: af_ZA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/af/LC_MESSAGES/pyLoadCli.po b/locale/af/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..1b0d1172a --- /dev/null +++ b/locale/af/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Afrikaans\n" +"Language: af_ZA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/af/LC_MESSAGES/setup.po b/locale/af/LC_MESSAGES/setup.po new file mode 100644 index 000000000..8aae41ce1 --- /dev/null +++ b/locale/af/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Afrikaans\n" +"Language: af_ZA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/ar/LC_MESSAGES/django.po b/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 000000000..6e67693ed --- /dev/null +++ b/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Arabic\n" +"Language: ar_SA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Ø·ÙÙÙØšØª ÙØ§ØšØªØŽØ§ Ø¬Ø¯ÙØ¯Ø©" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "ÙØ¶ÙØ§Ù Ø§ÙØ±Ø£ اÙÙØµÙ اÙÙ
ÙØ¬Ùد Ù٠اÙÙØ§ØšØªØŽØ§." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "Ø£Ø¹ÙØ¯ ت؎غÙÙ pyLoad" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "اÙÙØ§Ù" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "ÙØ¬Ø" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "ت؎غÙÙ" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Ø£Ù
ØªØ£ÙØ¯ Ù
٠أÙÙ ØªØ±ÙØ¯ Ø§ÙØ®Ø±Ùج Ù
Ù pyLoad Ø" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "أعد ؚدء Ø§ÙØ±Ø§ØšØ·" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Ø§ØØ°Ù Ø§ÙØ±Ø§ØšØ·" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "أدخ٠اسÙ
ا٠ÙÙØØ²Ù
Ø©." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "ÙØ¶Ùا٠اضغط عÙ٠اÙÙ
ÙÙØ¹ Ø§ÙØµØÙØ ÙÙÙØ§ØšØªØŽØ§." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "ØØ¯Ø« خطأ." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "اÙÙ
Ø¬ÙØ¯ ÙØ§Ø±Øº" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "ÙØŽÙ" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "ÙØ§ تتÙÙØ± ÙØ§ØšØªØŽØ§ ÙØ£ÙØ±Ø£ÙØ§." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "ÙÙ
تتطاؚ٠ÙÙÙ
تا اÙÙ
Ø±ÙØ±." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "ØÙÙÙØžÙت Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯Ø§Øª" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Ù
Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Ø£Ù
ØªØ£ÙØ¯ Ù
٠أÙÙ ØªØ±ÙØ¯ إعادة ت؎غÙÙ pyLoadØ" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "Ø§ÙØªØžØ§Ø± %" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Ø§ÙØªÙزÙÙØ§Øª اÙÙØŽØ·Ø©" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "اÙÙ
ÙØ²Ù" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "ÙØ§ØŠÙ
Ø© Ø§ÙØ¥Ùت؞ار" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "جاÙ
ع Ø§ÙØ±Ùاؚط" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Ø§ÙØªÙزÙÙØ§Øª" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Ø§ÙØ³Ø¬Ùات" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Ø§ÙØ¶ØšØ·" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "اسÙ
" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Ø§ÙØØ§ÙØ©" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Ù
عÙÙÙ
ات" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Ø§ÙØØ¬Ù
" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Ø§ÙØªÙدÙ
" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "تسجÙÙ Ø§ÙØ¯Ø®ÙÙ" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "اسÙ
اÙÙ
ستخدÙ
" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "ÙÙÙ
Ø© اÙÙ
Ø±ÙØ±" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "ÙÙ
ÙØªØ·Ø§ØšÙ اسÙ
اÙÙ
ستخدÙ
ÙÙÙÙ
Ø© اÙÙ
Ø±ÙØ± اÙÙØ°Ø§Ù Ø£Ø¯Ø®ÙØªÙÙ
ا. Ø±Ø¬Ø§Ø¡Ù ØØ§ÙÙ Ù
Ø¬Ø¯ÙØ¯Ø§Ù." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "ÙØ¥Ø¹Ø§Ø¯Ø© ضؚط ØšÙØ§Ùات اÙÙÙÙØ¬ Ø£Ù Ø¥Ø¶Ø§ÙØ© Ù
ستخدÙ
ÙÙÙØ°:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "تÙ
Ù Ø§ÙØØ°Ù" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "ÙØŽÙت إعادة Ø§ÙØªØŽØºÙÙ" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "اÙÙ
Ø¬ÙØ¯:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "ÙÙÙ
Ø© Ø§ÙØ³Ø±:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "ØØ±Ùر Ø§ÙØØ²Ù
Ø©" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "ØØ±Ùر ØªÙØ§ØµÙÙ Ø§ÙØØ²Ù
Ø© Ø£Ø¯ÙØ§Ù." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "اسÙ
Ø§ÙØØ²Ù
Ø©." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Ù
Ø¬ÙØ¯" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "اسÙ
اÙÙ
جÙÙØ¯ اÙÙØ±Ø¹ÙÙ ÙÙØ°Ù Ø§ÙØªÙزÙÙØ§Øª." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "ÙØ§ØŠÙ
Ø© ÙÙÙ
ات Ø§ÙØ³Ø± اÙÙ
ستخدÙ
Ø© ÙÙÙ٠ضغط rar" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Ø§ÙØªØ±Ø" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "اÙ
ØÙ" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "ÙÙØ¯ خرجت ØšÙØ¬Ø§Ø." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "اÙÙ
سار" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "Ù
ÙØ·ÙÙÙ" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "ÙØ³ØšÙ" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "Ø§ÙØ§Ø³Ù
" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "Ø§ÙØØ¬Ù
" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "اÙÙÙØ¹" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "آخر تغÙÙØ±" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "اÙÙ
Ø¬ÙØ¯ Ø§ÙØ£Øš" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "ÙØ§ Ù
ØØªÙÙ" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "عاÙ
" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "اÙÙ
ÙØÙØ§Øª" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Ø§ÙØØ³Ø§ØšØ§Øª" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "اختر ÙÙØ³Ù
ا٠Ù
٠اÙÙØ§ØŠÙ
Ø©" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Ø§ÙØ§Ø¶Ø§Ùات" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "ØµØ§ÙØØ© ØØªÙ" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "اÙÙÙØª" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Ø£ÙØµÙ عدد ÙÙØªÙزÙÙØ§Øª اÙÙ
تزاÙ
ÙØ©" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "ØØ°ÙØ" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "ØµØ§ÙØØ©" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "ØºÙØ± ØµØ§ÙØ" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "ÙØ¹Ù
" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "ÙØ§" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Ø¥Ø¶Ø§ÙØ©" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Ø¥Ø¶Ø§ÙØ© ØØ³Ø§Øš" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "أض٠Ù
عÙÙÙ
ات ØØ³Ø§ØšÙ ÙØªØ³ØªØ®Ø¯Ù
Ù
Ø²Ø§ÙØ§ Ø§ÙØØ³Ø§Øš اÙÙ
ØªÙØ¯ÙÙ
" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "اسÙ
ØØ³Ø§ØšÙ." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "ÙÙÙ
Ø© Ø§ÙØ³Ø±Ù ÙÙØ°Ø§ Ø§ÙØØ³Ø§Øš." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "ÙÙØ¹" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "اختر اÙÙ
ضÙÙ ÙØØ³Ø§ØšÙ." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "اؚدأ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "Ø§ÙØ³Ø§ØšÙ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "Ø§ÙØªØ§ÙÙ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Ø§ÙØªÙÙ" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "أخؚار" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Ø§ÙØ¯Ø¹Ù
" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "اÙÙØžØ§Ù
" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "ØšØ§ÙØ«ÙÙ:" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "ÙØžØ§Ù
Ø§ÙØªØŽØºÙÙ:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "إصدار pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Ù
Ø¬ÙØ¯ Ø§ÙØªØ«ØšÙت:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Ù
Ø¬ÙØ¯ Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯Ø§Øª:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Ù
Ø¬ÙØ¯ Ø§ÙØªÙزÙÙØ§Øª:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "اÙÙ
Ø³Ø§ØØ© Ø§ÙØØ±ÙØ©:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "اÙÙÙÙØºØ©:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Ù
ÙÙØ° ÙØ§Ø¬ÙØ© Ø§ÙØŽÙÙØšÙØªÙØ©:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Ù
ÙÙØ° اÙÙØ§Ø¬ÙØ© Ø§ÙØšØ¹Ùدة:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "ØšØ±ÙØ§Ù
ج Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Ù
Ø¯ÙØ± اÙÙ
ÙÙØ§Øª" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Ø£Ø¶Ù ØØ²Ù
Ø©" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Ø§ÙØµÙ راؚطأ Ø£Ù Ø§Ø±ÙØ¹ ØØ§ÙÙØ§Ù. " + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "اسÙ
Ø§ÙØØ²Ù
Ø© Ø§ÙØ¬Ø¯Ùدة." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Ø±ÙØ§ØšØ·" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Ø§ÙØµÙ Ø§ÙØ±Ùاؚط أ٠أÙÙ ÙØµÙ ÙÙØ§ Ø«Ù
اضغط زر٠استخراج Ø§ÙØ±Ùاؚط." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Ø±ØŽÙØ Ø§ÙØ±Ùاؚط" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "ÙÙÙ
Ø© سر أر؎ÙÙØ§Øª RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Ù
ÙÙ" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Ø§Ø±ÙØ¹ ØØ§ÙÙØ§Ù." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "اÙÙØ¬ÙØ©" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "اÙÙØµ" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Ø¥ØºÙØ§Ù" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "ÙØ§Ø¬ÙØ© Ø§ÙØŽÙÙØšÙØªÙØ©" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "ÙØªÙÙÙØ± ØªØØ¯ÙØ« ÙÙØšØ±ÙاÙ
ج!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "تÙ
Ù ØªØØ¯ÙØ« Ø§ÙØ¥Ø¶Ø§ÙØ©Ø ÙØ±Ø¬Ù إعادة ت؎غÙÙ Ø§ÙØšØ±ÙاÙ
ج!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "ÙØ§ØšØªØŽØ§ ØªÙØªØžØ±" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "اخرج" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Ø£Ø¯ÙØ±" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "اÙÙ
عÙÙÙ
ات" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "ÙØ±Ø¬Ù اÙÙÙÙØ¬!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "تÙÙÙÙ" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Ø§ÙØºØ§Ø¡" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Ø§ÙØªÙزÙÙ:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "إعادة Ø§ÙØ§ØªØµØ§Ù:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Ø§ÙØ³Ø±Ø¹Ø©:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "اÙÙØŽØ·:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "أعد تØÙ
ÙÙ Ø§ÙØµÙØØ©" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "ÙØÙ
ÙÙ" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Ø§ÙØ¹Ùدة ÙØ£Ø¹ÙÙ" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "اخرج Ù
Ù pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "أعد ت؎غÙÙ pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "ÙØ¥Ø¶Ø§ÙØ© Ù
ستخدÙ
أ٠تغÙÙØ± ÙÙÙ
ات Ù
Ø±ÙØ± استخدÙ
:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "ÙØ§Ù
Ù: ØØ³Ø§Øš اÙÙ
Ø¯ÙØ± Admin Ù٠دا؊Ù
Ø§Ù Ø§ÙØµÙاØÙات اÙÙØ§Ù
ÙØ©!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "غÙÙØ± ÙÙÙ
Ø© Ø§ÙØ³Ø±Ù" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "اÙÙ
؎رÙ" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Ø§ÙØ£Ø°ÙÙ" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "غÙÙØ±" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "أدخ٠ÙÙÙ
Ø© Ø§ÙØ³Ø±Ù Ø§ÙØØ§ÙÙÙØ© ÙØ§ÙØ¬Ø¯ÙØ¯Ø©." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "اÙÙ
ستخدÙ
" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "ÙÙÙ
Ø© Ø§ÙØ³Ø±Ù Ø§ÙØØ§ÙÙØ©" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "ÙÙÙ
Ø© Ø³Ø±Ù Ø¬Ø¯ÙØ¯Ø©" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "ÙÙÙ
Ø© Ø§ÙØ³Ø±Ù Ø§ÙØ¬Ø¯Ùدة." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "ÙÙÙ
Ø© Ø§ÙØ³Ø±Ù Ø§ÙØ¬Ø¯Ùدة (إعادة)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "ÙØ¶Ùا٠أعد إدخا٠ÙÙÙ
Ø© Ø§ÙØ³Ø±Ù." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "ÙØ§ ÙÙØ¬Ø¯ ÙØ¯ÙÙ ØµÙØ§ØÙات ÙÙÙØµÙÙ ÙÙØ°Ù Ø§ÙØµÙØÙ" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Ù
Ø¬ÙØ¯ Ø§ÙØªØÙ
ÙÙØ§Øª ØºÙØ± Ù
ÙØ¬Ùد" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ØºÙØ± Ù
ØØ¯Ùد" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "ØºÙØ± Ù
تÙÙØ±" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÙÙ
ؚت؎غÙÙ pyload.py -s ÙØªØšØ¯Ø§Ø¡ Ø§ÙØªØ«ØšÙت" + diff --git a/locale/ar/LC_MESSAGES/pyLoad.po b/locale/ar/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..7acb978f5 --- /dev/null +++ b/locale/ar/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Arabic\n" +"Language: ar_SA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "تÙ
Ø§Ø³ØªÙØšØ§Ù ا؎ارة اÙÙØ§Ø¡" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "ؚا٠ÙÙØ¯ ÙØ¹Ù
Ù ØØ§ÙÙØ§ ØšÙ
Ø¹Ø±Ù Ø§ÙØ¹Ù
ÙÙØ© %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "ÙØŽÙ Ù٠تغÙÙØ± اÙÙ
جÙ
ÙØ¹Ù: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "ÙØŽÙ Ù٠تغÙÙØ± اÙÙ
ستخدÙ
: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "Ù
Ø¬ÙØ¯ ÙÙØªÙØ§Ø±ÙØ±" + +#: module/Core.py:340 +msgid "Starting" +msgstr "ؚدء" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "استخداÙ
Ù
Ø¬ÙØ¯ اÙÙ
ÙØ²Ù: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "Ù
Ø¬ÙØ¯ ÙÙÙ
ÙÙØ§Øª اÙÙ
Ø€ÙØªØ©" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "Ù
Ø¬ÙØ¯ ÙÙØªØÙ
ÙÙØ§Øª" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL ÙØ§ØªØµØ§Ù اÙ
Ù" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "ÙÙ٠اعدادت اÙÙ
ستخدÙ
اÙÙØ¯ÙÙ
اÙÙ ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "ÙØ±Ø¬Ù Ø§ÙØªØ§Ùد Ù
Ù ØšÙØ§Ùات Ø§ÙØ¯Ø®Ù٠ؚستخداÙ
./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "تÙ
Ù
Ø³Ø Ø¬Ù
ÙØ¹ Ø§ÙØ±Ùاؚط" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "ÙÙØª Ø§ÙØªØÙ
ÙÙ: %" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "اÙÙ
ساØÙ Ø§ÙØØ±Ù: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "ØªÙØ¹ÙÙ Ø§ÙØØ³Ø§ØšØ§Øª..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "ØªÙØ¹ÙÙ Ø§ÙØ§Ø¶Ø§Ùات..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "ؚا٠ÙÙØ¯ Ù
ØØ¯Ø« Ù ÙØ¹Ù
Ù" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "اعادة ت؎غÙ٠ؚا٠ÙÙØ¯" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "Ø§ØºÙØ§Ù ؚا٠ÙÙØ¯" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Ø§ÙØªØ«ØšÙت %" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "ÙØ§ ÙÙ
ÙÙ Ø§ÙØ¬Ø§Ø¯ %(ÙØµÙ): %(اسÙ
)" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "ÙØ§ ÙÙ
ÙÙ Ø§ÙØŽØ§Ø¡ %(ÙØµÙ): %(اسÙ
)" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "جار٠اÙÙØ§Ù Ø§ÙØªØŽØºÙÙ..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "خطاء Ø§Ø«ÙØ§Ø¡ اÙÙØ§Ù Ø§ÙØªØŽØºÙÙ " + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "اÙÙØ§Ø¡ ؚا٠ÙÙØ¯ Ù
Ù Ø§ÙØ·Ø±ÙÙÙ" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "تÙ
Ø§ÙØ§ÙØªÙØ§Ø¡" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "ØºÙØ± Ù
تصÙ" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "Ù
تصÙ" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "ÙÙ ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "تخطÙ" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "Ø§ÙØªØžØ§Ø±" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "Ù
Ø€ÙØª. ØºÙØ± Ù
تصÙ" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "Ø§ÙØšØ¯Ø¡" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "ÙØŽÙ" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "Ø§ÙØºØ§Ø¡" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "Ù٠ت؎ÙÙØ±" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "Ù
خصص" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "Ø¬Ø§Ø±Ù Ø§ÙØªÙزÙÙ" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "تجÙÙØ²" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "ØºÙØ± Ù
عرÙÙ" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Ø§ÙØªÙت Ø§ÙØØ²Ù
Ù: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "خطاء Ù٠اÙÙØ§Ø¬ÙØ© Ø§ÙØ®ÙÙÙÙ ÙÙØšØ±ÙاÙ
ج " + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "ؚدء %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "ÙØŽÙ Ù٠تØÙ
Ù٠اÙÙØ§Ø¬ÙÙ Ø§ÙØ®ÙÙÙÙ ÙÙØšØ±ÙاÙ
ج %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "Ø§ÙØªØžØ§Ø± %" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "ØŽÙØ§Ø¯Ø© SSL ØºÙØ± Ù
ÙØ¬ÙدÙ." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "ÙØ£Ø³Ù, ÙÙØ¯ اÙÙÙÙØ§ Ø§ÙØ¯Ø¹Ù
ÙÙØšØ¯ØŠ % Ù
ؚا؎ر٠Ù
٠ؚا٠ÙÙØ¯ " + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "عÙÙØ§Øª Ø§ÙØ§Ø¹Ø¯Ø§Ø¯Ø§Øª Ù
ÙØ¬Ùدة Ù٠اÙÙ
Ø¬ÙØ¯ module/webui/servers " + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "ÙØ§ÙÙ
Ù٠استخداÙ
%(خادÙ
), ÙÙ
ÙØªÙ
ØªØ«ØšÙØª python-flup!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "ØªØØªØ§Ø¬ ÙØªØÙ
ÙÙ Ù ØªØ«ØšÙØª bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Ø§ÙØ³Ø® boern.so اÙÙ module/lib ا٠استخدÙ
setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "ØšØ§ÙØ·ØšØ¹ ÙØ¬Øš ا٠تÙÙÙ Ù
عتاد عÙÙ ÙÙÙØ³ ÙØªØ¹Ø±Ù ÙÙ٠تثؚت Ø§ÙØšØ±Ø§Ù
ج" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "ÙØ°Ø§ اÙÙ
خدÙ
ÙØ§ ÙÙØ¯Ù
خدÙ
Ø© SSLØ ÙØ±Ø¬Ù اÙÙØžØ± Ù٠استخداÙ
ؚدÙÙØ§Ù Ù
٠ذÙÙ" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "ÙØ§ ÙÙØ¬Ø¯ ÙØ¯ÙÙ ØµÙØ§ØÙات ÙÙÙØµÙÙ ÙÙØ°Ù Ø§ÙØµÙØÙ" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Ù
Ø¬ÙØ¯ Ø§ÙØªØÙ
ÙÙØ§Øª ØºÙØ± Ù
ÙØ¬Ùد" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ØºÙØ± Ù
ØØ¯Ùد" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "ØºÙØ± Ù
تÙÙØ±" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÙÙ
ؚت؎غÙÙ pyload.py -s ÙØªØšØ¯Ø§Ø¡ Ø§ÙØªØ«ØšÙت" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "ÙØŽÙ Ø§ÙØªÙزÙ٠عÙ٠اجزاء, Ø§ÙØ¹Ùدة اÙÙ Ø§ÙØªÙزÙ٠عÙÙ Ø§ØªØµØ§Ù ÙØ§ØØ¯ | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "ؚدء Ø§ÙØªÙزÙÙ: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "تÙ
Ø§ÙØ§ÙØªÙØ§Ø¡ Ù
Ù Ø§ÙØªÙزÙÙ: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Ø§ÙØ§Ø¶Ø§ÙØ© %s ØªÙØªÙد اÙÙ ÙØžÙÙØ©." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "تÙ
Ø§ÙØºØ§Ø¡ Ø§ÙØªÙزÙÙ: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "تÙ
اعادة ت؎غÙÙ Ø§ÙØªÙزÙÙ: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Ø§ÙØªÙزÙÙ ØºÙØ± Ù
تصÙ: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Ø§ÙØªÙزÙÙ ØºÙØ± Ù
تص٠Ù
Ø€ÙØªØ§: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "ÙØŽÙ Ø§ÙØªÙزÙÙ: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "ÙØ§ÙÙ
Ù٠اÙÙØµÙ٠اÙÙ Ø§ÙØ®Ø§Ø¯Ù
ا٠اعادة Ø§ÙØ§ØªØµØ§Ù, Ø§ÙØ§Ùت؞ار 1 دÙÙÙØ© ٠اعادة اÙÙ
ØØ§ÙÙØ©." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "تÙ
ØªØ®Ø·Ù Ø§ÙØªÙزÙÙ: %(name)s ؚسؚؚ %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "ÙØŽÙ Ø¬ÙØš Ø§ÙÙ
عÙÙÙ
ات Ù %(name)s | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "ÙØŽÙ Ø§ÙØªÙعÙÙ %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Ø§ÙØ§Ø¶Ø§Ùات اÙÙ
ÙØ¹ÙØ©: %" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Ø§ÙØ§Ø¶Ø§Ùات اÙÙ
Ø¹Ø·ÙØ©: %" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "ÙØŽÙ Ù٠اعادة Ø§ÙØ§ØªØµØ§Ù: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Ø§ÙØšØ±ÙاÙ
ج اÙÙØµÙ ÙØ§Ø¹Ø§Ø¯Ø© Ø§ÙØ§ØªØµØ§Ù ØºÙØ± Ù
تÙÙØ±!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "ؚدء اعادة Ø§ÙØ§ØªØµØ§Ù" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "ÙØŽÙ Ù٠تÙÙÙØ° Ø§ÙØšØ±ÙاÙ
ج اÙÙØµÙ ÙØ§Ø¹Ø§Ø¯Ø© Ø§ÙØ§ØªØµØ§Ù!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "تÙ
ت اعادة Ø§ÙØ§ØªØµØ§Ù, IP Ø¬Ø¯ÙØ¯: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "ÙÙ
ÙØªØšÙÙ Ù
Ø³Ø§ØØ© ÙØ§ÙÙØ© عÙÙ Ø§ÙØ¬Ùاز" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "ÙØ§ ÙÙ
Ù٠تسجÙÙ Ø§ÙØ¯Ø®ÙÙ ØšÙØ°Ø§ Ø§ÙØØ³Ø§Øš %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "ÙÙÙ
Ø© Ù
Ø±ÙØ± خاط؊ة" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "Ø§ÙØØ³Ø§Øš %s ÙÙØ³ ÙÙØ© ÙÙ
ÙØ© ØšÙØ§Ùات ÙØ§ÙÙØ©, اعد Ø§ÙØªØÙÙ Ø®ÙØ§Ù 30 دÙÙÙØ©" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "Ø§ÙØªÙت Ù
دة Ø§ÙØØ³Ø§Øš %s, تØÙÙ Ù
رة اخر٠ÙÙ 1 ساعة" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "ÙÙØ¯ ÙØµÙت اÙÙ Ø§ÙØØ¯ Ø§ÙØ§Ùص٠ÙÙØªÙزÙÙ" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "خطأ ÙÙ Ø§Ø³ØªÙØ±Ø§Ø¯ %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "ÙØ§ Ù
ستضÙÙ Ù
ØÙ
Ù" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "ÙÙ
ØšØªÙØ¹ÙÙ Ø§ÙØªØÙ
Ù٠اÙÙ
ؚا؎ر ÙÙ ØØ³Ø§Øš Bitshare ÙØ¯ÙÙ" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Ù
Ø·ÙÙØš ØªØµØ±ÙØ (اسÙ
Ù
ستخدÙ
: ÙÙÙ
Ø© Ù
Ø±ÙØ±)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø¯Ø®Ø§Ù ØØ³Ø§ØšÙ ÙÙ %s Ø£Ù Ø¥ÙØºØ§Ø¡ ØªÙØŽÙØ· ÙØ°Ø© Ø§ÙØ§Ø¶Ø§ÙØ©" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "ÙÙØ§Ù رÙ
ز HTML Ù٠اÙÙ
ÙÙØ§Øª اÙÙØªÙ تÙ
ØªÙØ²ÙÙÙØ§ (%s)...خطاء اعادة ØªÙØ¬ÙØ©ØØ³ÙÙ ÙØªÙ
اعادة ت؎غÙÙ Ø§ÙØªÙزÙÙ." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "اÙÙ
ÙÙ ØºÙØ± Ù
تÙÙØ± Ù
Ø€ÙØªØ§" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "ضغط Ø§ÙØŽØšÙØ©: Ø§ÙØ§Ùت؞ار ØšÙÙ Ø§ÙØªÙزÙÙØ§Øª %d." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "ضغط Ø§ÙØŽØšÙØ©: Ø§ÙØ§Ùت؞ار Ù
٠اج٠ÙÙÙ
Ø© Ø§ÙØªØÙÙ%d." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "اÙÙ
Ù٠اÙÙØ°Ù تÙ
ØªÙØ²ÙÙØ© ÙØ§Ø±Øº" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "Ù
ÙØªØ§Ø ÙØ§ØÙØ© ؚرÙ
جة Ø§ÙØªØ·ØšÙÙØ§Øª ØºÙØ± ØµØ§ÙØ" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: ÙÙ
ÙØªØšÙÙ ÙØ¯ÙÙ ØšÙØ§Ùات ÙØ§ÙÙØ©" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "تÙ
ØªØ¬Ø§ÙØ² Ø§ÙØšÙØ§ÙØ§Øª اÙÙ
تÙÙØ±Ø©" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: ØšÙØ§Ùات اÙÙ
ØŽØ§Ø±ÙØ© (تØÙ
ÙÙ Ù
ؚا؎ر)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Ø¬Ø§Ø±Ù Ø§ÙØªØÙ
ÙÙ Ù
٠عÙÙØ§Ù Ø§ÙØ§ÙØªØ±ÙØª ÙØ°Ø§, Ø§ÙØªØžØ± Ù 60 ثاÙÙØ©" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "رÙ
ز تاÙÙØ¯ ØºÙØ± ØµØ§ÙØ, سÙÙ ÙØªÙ
اعادة Ø§ÙØªÙزÙÙ" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: ÙØ§ ÙÙØ¬Ø¯ Ù
Ø³Ø§ØØ§Øª ÙØ§Ø±ØºØ©" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "تØÙاج ÙØØ³Ø§Øš Ù
دÙÙØ¹ Ù
Ù Ø§Ø¬Ù ÙØ°Ø§ اÙÙ
ÙÙ" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "تÙ
Ø§ÙØ§ØšÙاغ ع٠اسÙ
اÙÙ
ÙÙ ØºÙØ± ØµØ§ÙØ" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "خطاء ØªÙØ²ÙÙØ§Øª Ù
ØªÙØ§Ø²ÙØ©, Ø§ÙØ§Ù Ø§ÙØªØžØ± 60 ثاÙÙØ©." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "ÙÙ
ÙØªÙ
تسجÙÙ Ø§ÙØ¯Ø®ÙÙ." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "ÙØŽÙ ÙÙ ÙÙ Ø§ÙØªØŽÙÙØ±" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "ÙØ§ ÙÙØ¬Ø¯ Ù
ÙØªØ§Ø Ù
ÙÙ Ù
ÙØ¯Ù
Ù٠عÙÙØ§Ù Ø§ÙØ§ÙØªØ±ÙØª" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "رÙ
ز خطاء:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** تÙ
ØªØØ¯ÙØ« Ø§ÙØ§Ø¶Ø§Ùات, ÙØ±Ø¬Ù اعادة ت؎غÙ٠ؚا٠ÙÙØ¯ ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "تÙ
ØªØØ¯ÙØ« Ø§ÙØ§Ø¶Ø§Ùات ٠اعادة ت؎غÙÙÙØ§" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "ÙØ§ ÙÙØ¬Ø¯ ØªØØ¯Ùثات ÙÙØ§Ø¶Ø§Ùات" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "ÙØ§ÙÙØ¬Ø¯ ØªØØ¯Ùثات ٠ؚا٠ÙÙØ¯" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** ÙØ³Ø®Ù Ø¬Ø¯ÙØ¯Ù %s Ù
٠ؚا٠ÙÙØ¯ Ù
تÙÙØ±Ù ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Ø§ØØµÙ عÙÙÙØ§ Ù
Ù ÙÙØ§: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "ØºÙØ± ÙØ§Ø¯Ø± عÙÙ Ø§ÙØ§ØªØµØ§Ù ØšØ§ÙØ®Ø§Ø¯Ù
Ù
Ù Ø§Ø¬Ù Ø§ÙØªØØ¯ÙØ«" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "ÙØ³Ø®Ù Ø¬Ø¯ÙØ¯Ø© Ù
Ù %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "ØØµÙ خطاء Ø¹ÙØ¯ Ø§ÙØªØØ¯ÙØ« %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "ÙØ³Ø®Ø© ØºÙØ± Ù
ØªØ·Ø§ØšÙØ©" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Ø§ÙØªÙÙ Ø§ÙØªÙزÙÙ: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Ø·ÙØš ÙÙÙ
Ø© تØÙÙ Ø¬Ø¯ÙØ¯: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "اجؚ Øš 'c %s ÙØµ عÙÙ ÙÙÙ
Ø© Ø§ÙØªØÙÙ'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "اضاÙÙ %s Ù
Ù HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "ÙØ§ %s Ù
ثؚت" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "ÙØ§ ÙÙ
ÙÙ ØªÙØ¹ÙÙ %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "تÙ
Ø§ÙØªÙعÙÙ" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "ÙØ§ Ø§Ø¶Ø§ÙØ§Øª استخراج Ù
ÙØ¹ÙØ©" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Ø§ÙØØ²Ù
Ù %s ÙÙ ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار ÙÙØ§Ø³ØªØ®Ø±Ø§Ø¬ ÙØ§ØÙا" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "ØªÙØØµ Ø§ÙØØ²Ù
%s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "استخراج اÙÙ %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "ÙÙ
ÙØªÙ
Ø§ÙØ¹Ø«Ùر عÙÙ Ù
ÙÙØ§Øª ÙÙØ§Ø³ØªØ®Ø±Ø§Ø¬" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "ÙÙ Ø§ÙØžØºØ·" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Ù
ØÙ
Ù ØšÙÙÙ
Ø© Ù
Ø±ÙØ±" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "ÙÙÙ
Ø© Ù
Ø±ÙØ± خاط؊ة" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "ØØ°Ù %s اÙÙ
ÙÙØ§Øª" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "تÙ
Ø§ÙØ§ÙØªÙØ§Ø¡ Ù
Ù Ø§ÙØ§Ø³ØªØ®Ø±Ø§Ø¬" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "خطأ ÙÙ Ø§ÙØ£Ø±ØŽÙÙ" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC ØºÙØ± Ù
تطاؚÙ" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "خطاء ØºÙØ± Ù
عرÙÙ" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "ÙØŽÙ ÙÙ ØªØØ¯Ùد اÙÙ
ستخدÙ
٠اÙÙ
جÙ
ÙØ¹Ø©" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "ضغط ٠تØÙ
ÙÙ: Ù
ÙÙØ° 9666 ÙÙØ¯ Ø§ÙØ§Ø³ØªØ®Ø¯Ø§Ù
" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%sØ±ØµÙØ¯ Ù
تؚÙÙ" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "ÙØ§ÙÙ
Ù٠ارسا٠رد." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "ØØ³Ø§ØšÙ ÙÙ CaptchaTrader ÙØ§ ÙØØªÙÙ Ø±ØµÙØ¯ ÙØ§ÙÙ" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "ÙÙ
ÙØªÙ
Ø§ÙØ¹Ø«Ùر عÙÙ ÙØ§ØŠÙ
Ø© Crypter" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "ÙØ§ØŠÙ
Ø© Crypter ÙØ§Ø±ØºØ©" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Ø§ÙØªÙÙ Ø§ÙØªØÙ
ÙÙ: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "ÙÙÙØ© تØÙÙ Ø¬Ø¯ÙØ¯Ø© Ù
Ù upload: %s :%s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "ØØ³Ø§ØšÙ ÙÙØªØÙÙ 9kw.eu ÙØ§ ÙØØªÙ٠عÙÙ Ø±ØµÙØ¯ ÙØ§ÙÙ" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Ø³ÙØ±ØšØª Ù
ثؚت Ù %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Ø³ÙØ±ØšØª ØºÙØ± ÙØ§ØšÙ ÙÙØªÙÙÙØ°:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "خطاء ÙÙ %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "ÙÙ
ÙØªØšÙÙ ÙØ¯ÙÙ Ø±ØµÙØ¯ ÙØ§ÙÙ ÙÙ ØØ³Ø§Øš ExpertDecoders ÙØ¯ÙÙ" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "ÙØ±Ø¬Ù Ø§Ø¶Ø§ÙØ© ØØ³Ø§Øš rehost.to اÙÙØ§ Ø«Ù
اعاد٠ت؎غÙ٠ؚا٠ÙÙØ¯" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d Ø±ØµÙØ¯ Ù
تؚÙÙ" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "pil Ù tesseract ØºÙØ± Ù
ثؚت ÙÙØ§ÙÙØ¬Ø¯ عÙ
ÙÙ Ù
تص٠ÙÙÙ ÙÙÙ
Ø© Ø§ÙØªØÙÙ" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "ÙØŽÙ Ù٠اعداد اÙÙ
ستخدÙ
٠اÙÙ
جÙ
ÙØ¹Ù: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "ÙØ§ÙÙØ¬Ø¯ عÙ
ÙÙ Ù
تص٠ÙÙ٠ت؎ÙÙØ± اÙÙØ§ØšØ§ØªØŽØ§" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "ØØ²Ù
Ù
ضاÙÙ %(اسÙ
) ØªØØªÙÙ %(عدد) Ø±ÙØ§ØšØ·" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Ù
ضاÙÙ %(عدد) Ø±ÙØ§ØšØ· اÙÙ Ø§ÙØØ²Ù
Ù #%(ØØ²Ù
)" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "ÙÙ
ÙØªÙ
Ø§ÙØ¹Ø«Ùر عÙÙ Ù
ØØ±Ù js, ÙØ±Ø¬Ù ØªØ«ØšÙØª Spidermonkey, ossp-js, pyv8 ا٠rhino" + diff --git a/locale/ar/LC_MESSAGES/pyLoadCli.po b/locale/ar/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..68d792617 --- /dev/null +++ b/locale/ar/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Arabic\n" +"Language: ar_SA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " ÙØ§Ø¬ÙØ© سطر Ø§ÙØ£ÙاÙ
ر" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s Ø§ÙØªÙزÙÙØ§Øª:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Ø§ÙØ³Ø±Ø¹Ø©: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Ø§ÙØØ¬Ù
: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Ø§ÙØ§ÙØªÙØ§Ø¡ ÙÙ: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " Ù
عرÙ: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "ÙÙ Ø§ÙØªØžØ§Ø±: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Ø§ÙØØ§ÙØ©:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "تÙ
Ø¥ÙÙØ§Ù Ù
Ø€ÙØªØ§Ù" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "ت؎غÙÙ" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "Ø§ÙØ³Ø±Ø¹Ø© Ø§ÙØ¥Ø¬Ù
اÙÙØ©" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "اÙÙ
ÙÙØ§Øª اÙÙ
ÙØ¬Ùدة ÙÙ ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "اÙÙ
جÙ
ÙØ¹" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "اÙÙØ§ØŠÙ
Ø©:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Ø§Ø¶Ø§ÙØ© Ø±ÙØ§ØšØ·" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " إدارة ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " إدارة جاÙ
ع Ø§ÙØ±Ùاؚط" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " (عدÙ
) اÙÙØ§Ù Ù
Ø€ÙØª ÙÙØ®Ø§Ø¯Ù
" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " ÙØªÙ Ø§ÙØ®Ø§Ø¯Ù
" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Ø¥ÙÙØ§Ø¡" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Ø§ÙØ±Ø¬Ø§Ø¡ استخداÙ
ØšÙØ§Ø¡ Ø§ÙØ¬Ù
ÙØ© Ø§ÙØªØ§ÙÙ: Ø¥Ø¶Ø§ÙØ© <Package name><link><link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Ø§ÙØªØÙÙ %d Ù
Ù Ø§ÙØ±Ùاؚط:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "اÙÙ
ÙÙ ØºÙØ± Ù
ÙØ¬Ùد." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "تÙ
اÙÙØ§Ø¡ ؚا٠ÙÙØ¯" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "اطؚع ØØ§ÙØ© Ø§ÙØ®Ø§Ø¯Ù
" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Ø§ÙØªØš Ø§ÙØªÙزÙÙØ§Øª اÙÙØªÙ ÙÙ ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Ø§ÙØªØš Ø§ÙØªÙزÙÙØ§Øª اÙÙØªÙ Ù٠جاÙ
ع Ø§ÙØ±Ùاؚط" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Ø§Ø¶Ø§ÙØ© ØØ²Ù
Ø© اÙÙ ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Ø§Ø¶Ø§ÙØ© ØØ²Ù
Ø© Ø¥Ù٠جاÙ
ع Ø§ÙØ±Ùاؚط" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "ØØ°Ù اÙÙ
ÙÙØ§Øª Ù
Ù ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار/جاÙ
ع Ø§ÙØ±Ùاؚط" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "ØØ°Ù ØØ²Ù
Ù
Ù ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار/جاÙ
ع Ø§ÙØ±Ùاؚط" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "ÙÙÙ Ø§ÙØØ²Ù
Ù
Ù ÙØ§ØŠÙ
Ø© Ø§ÙØ§Ùت؞ار Ø¥Ù٠جاÙ
ع Ø§ÙØ±Ùاؚط Ø£Ù Ø§ÙØ¹Ùس ØšØ§ÙØ¹Ùس" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "إعادة ت؎غÙ٠اÙÙ
ÙÙØ§Øª" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "إعادة ت؎غÙÙ Ø§ÙØØ²Ù
" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "تØÙÙ Ù
Ù ØØ§ÙØ© Ø§ÙØ§ØªØµØ§ÙØ ÙØ¹Ù
Ù Ù
ع اÙÙ
ØØªÙ٠اÙÙ
ØÙÙ" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Ø§ÙØªØÙÙ Ù
Ù ØØ§ÙØ© Ø§ÙØ§ØªØµØ§Ù Ù
٠اÙÙ
Ù٠اÙÙ
ØØªÙÙ" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Ø¥ÙÙØ§Ù Ø§ÙØ®Ø§Ø¯Ù
Ù
Ø€ÙØªØ§" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "Ù
تاؚعة Ø§ÙØªÙزÙÙØ§Øª" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "تؚدÙ٠إÙÙØ§Ù/عدÙ
اÙÙØ§Ù Ø§ÙØ¥ÙÙØ§Ù اÙÙ
Ø€ÙØª" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "ÙØªÙ Ø§ÙØ®Ø§Ø¯Ù
" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "ÙØ§ØŠÙ
Ø© Ø§ÙØ£ÙاÙ
ر:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "ÙØ§ ÙÙ
ÙÙ ÙØªØ§ØšØ© Ù
Ù٠اعدادات اÙÙ
ستخدÙ
" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Ø§ÙØ¹ÙÙØ§Ù: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "اÙÙ
ÙÙØ°: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "اسÙ
اÙÙ
ستخدÙ
: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "ÙÙÙ
Ø© اÙÙ
Ø±ÙØ±: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "ØšÙØ§Ùات تسجÙÙ Ø§ÙØ¯Ø®Ù٠خاط؊ة." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "ÙØ§ ÙÙ
ÙÙ Ø§ÙØŽØ§Ø¡ اتصا٠%(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Ø£ÙØª ØšØØ§Ø¬Ø© Ø¥ÙÙ py-openssl ÙÙØ§ØªØµØ§Ù ØšÙØ°Ø§ Ø§ÙØ§Ø³Ø§Ø³ Ù
٠ؚا٠ÙÙØ¯." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "اÙÙØ¶Ø¹ Ø§ÙØªØšØ§Ø¯Ù٠تÙ
تجاÙÙÙ ØÙØ« اÙÙ Ù
ررت ؚعض Ø§ÙØ§ÙاÙ
ر." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Ø¥Ø¶Ø§ÙØ© ØØ²Ù
Ø©:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "أدخ٠اسÙ
ا٠ÙÙØØ²Ù
Ø© Ø§ÙØ¬Ø¯Ùدة" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Ø§ÙØØ²Ù
Ø©: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "تØÙÙÙ Ø§ÙØ±Ùاؚط Ø§ÙØªÙ ØªØ±ÙØ¯ Ø¥Ø¶Ø§ÙØªÙا." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Ø§ÙØªØš %s Ø¹ÙØ¯ Ø§ÙØ§ÙØªÙØ§Ø¡." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "تÙ
Ø§Ø¶Ø§ÙØ© Ø§ÙØ±Ùاؚط: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " Ø§ÙØ¹Ùدة Ø¥Ù٠اÙÙØ§ØŠÙ
Ø© Ø§ÙØ±ØŠÙØ³ÙØ©" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "إدارة Ø§ÙØØ²Ù
:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "إدارة Ø§ÙØ±Ùاؚط:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Ù
ا اÙÙØ°Ù ØªØ±ÙØ¯ ÙÙÙØ© Ø" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Ù
ا اÙÙØ°Ù ØªØ±ÙØ¯ ØØ°ÙØ© Ø" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Ù
ا اÙÙØ°Ù ØªØ±ÙØ¯ اعادة ت؎غÙÙØ© Ø" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "ØØ°Ù" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "ÙÙÙ" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "إعادة ت؎غÙÙ" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " -Ø§ÙØ³Ø§ØšÙØ©" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " -Ø§ÙØªØ§ÙÙ" + diff --git a/locale/ar/LC_MESSAGES/setup.po b/locale/ar/LC_MESSAGES/setup.po new file mode 100644 index 000000000..b9b466981 --- /dev/null +++ b/locale/ar/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Arabic\n" +"Language: ar_SA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Ù
Ø±ØØšØ§ ØšÙÙ
ÙÙ Ù
ساعد اعداد ؚا٠ÙÙØ¯ ." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "سÙÙ ÙØªÙ
ÙØØµ ÙØžØ§Ù
Ù ÙØ¹Ù
Ù ØªØ«ØšÙØª اÙÙÙ Ù
٠اج٠ت؎غÙ٠ؚا٠ÙÙØ¯." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "اÙÙÙÙ
Ø© اÙÙ
ÙØ¬Ùدة ÙÙ Ø§ÙØ£ÙÙØ§Ø³ [] Ù٠دا؊Ù
ا٠اÙÙÙÙ
Ø© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ©Ø" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "ÙÙ ØØ§Ù ÙÙØª ÙØ§ ترغؚ Ù٠تغÙÙØ±Ùا Ø£Ù ÙÙØª ØºÙØ± Ù
ØªØ£ÙØ¯ Ù
Ù Ù
ا ØªØ®ØªØ§Ø±Ø ÙÙØ· اضغط أدخاÙ." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "ÙØ§ ØªÙØ³Ù: ÙÙ
ÙÙ٠دا؊Ù
ا٠إعادة ت؎غÙÙ ÙØ°Ø§ اÙÙ
ساعد ؚستخداÙ
--setup Ø£Ù-s اÙÙ
عÙÙ
Ø©Ø Ø¹ÙØ¯ ؚدء ت؎غÙÙ pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "ÙÙØ§ÙÙØ§Ø¡Ø ÙØ¹Ø¯Ù
Ø§ÙØ³Ù
Ø§Ø ÙÙ Ø§ÙØšØ¯ØŠ Ù
ع pyload.py تÙÙØ§ØŠÙا٠ؚعد Ø§ÙØ¢Ù." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Ø¹ÙØ¯Ù
ا تÙÙ٠عÙ٠استعداد ÙÙØªØÙÙ Ù
٠اÙÙØžØ§Ù
Ø Ø§Ø¶ØºØ· Ù
ÙØªØ§Ø Ø§ÙØ§Ø¯Ø®Ø§Ù." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "ÙØ§Ø¬ÙØ© Ø§ÙØŽÙÙØšÙØªÙØ©" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Ø§ÙØ§Ø³ØªÙ
رار ÙÙ Ø§ÙØªÙØµÙØšØ" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "ÙÙ ØªØ±ÙØ¯ ØªØºÙØ± Ù
ÙØ§Ù Ø§ÙØ§Ø¹Ø¯Ø§Ø¯Ø§ØªØ Ø§ÙØØ§ÙÙ ÙÙ %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "تغÙÙØ± Ù
سار Ø§ÙØ§Ø¹Ø¯Ø§Ø¯Ø" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "ÙÙ ØªØ±ÙØ¯ اعداد Ø§ÙØ§Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØ£Ø³Ø§Ø³ÙØ© ÙØšÙØ§ÙØ§Øª Ø§ÙØ¯Ø®ÙÙØ" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "ÙØ°Ø§ Ù
Ø³ØªØØ³Ù Ù
Ù Ø§Ø¬Ù Ø§ÙØªØŽØºÙÙØ© Ø§ÙØ§ÙÙÙ." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "ØµÙØ¹ Ø§ÙØ§Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØ§Ø³Ø§Ø³ÙØ©Ø" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "ÙÙ ØªØ±ÙØ¯ اعداد sslØ" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "اعداد sslØ" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "ÙÙ ØªØ±ÙØ¯ اعداد ÙØ§ØÙØ© اÙÙÙØšØ" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "اعداد ÙØ§Ø¬ÙØ© اÙÙÙØšØ" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "تÙ
اÙÙØ§Ø¡ Ø§ÙØªØ«ØšÙت ØšÙØ¬Ø§Ø." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "اضغ؞ Ù
ÙØªØ§Ø Ø§ÙØ§Ø¯Ø®Ø§Ù ÙÙØ§ÙÙØ§Ø¡ ٠اعادة ت؎غÙ٠ؚا٠ÙÙØ¯" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "# # Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ Ø§ÙØ£Ø³Ø§Ø³Ù # #" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "ØšÙØ§Ùات تسجÙÙ Ø§ÙØ¯Ø®ÙÙ Ø§ÙØªØ§ÙÙØ© ØµØ§ÙØØ© ÙÙØ§Ø¬ÙØ© سطر Ø§ÙØ§ÙاÙ
ر, ÙØ§Ø¬ÙØ© اÙÙ
ستخدÙ
Ù ÙØ§Ø¬ÙØ© اÙÙÙØš." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "اسÙ
اÙÙ
ستخدÙ
" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "اÙÙØºØ©" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Ø§ÙØ¹Ø¯Ø¯ Ø§ÙØ§ÙØµÙ Ø§ÙØªÙزÙÙØ§Øª اÙÙ
ØªÙØ§Ø²ÙÙØ© (Ø§ÙØªÙزÙÙØ§Øª ÙÙ ÙÙØ³ اÙÙÙØª)" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "استخداÙ
إعادة Ø§ÙØ§ØªØµØ§ÙØ" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Ù
ÙÙØ¹ Ø§ÙØšØ±ÙاÙ
ج اÙÙØµÙ ÙØ§Ø¹Ø§Ø¯Ø© Ø§ÙØ§ØªØµØ§Ù" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "# # اعداد ÙØ§Ø¬ÙØ© اÙÙÙØš # #" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "ØªÙØŽÙØ· ÙØ§Ø¬ÙØ© اÙÙÙØšØ" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "عÙÙØ§Ù اÙÙØ§Ø¬ÙØ©, اذا ÙÙ
ت ؚستخداÙ
127.0.0.1 ا٠localhost, ÙØ§Ø¬ÙØ© اÙÙÙØš Ø³Ù٠تÙÙÙ ÙØ§ØšÙØ© ÙÙÙØµÙÙ Ù
ØÙÙØ§ ÙÙØ·." + +#: module/setup.py:312 +msgid "Address" +msgstr "عÙÙØ§Ù" + +#: module/setup.py:313 +msgid "Port" +msgstr "اÙÙ
ÙÙØ°" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "ÙÙØ¯Ù
ؚا٠ÙÙØ¯ Ø®ÙØ§Ø¯Ù
Ù
تعددة ÙÙÙØ§Ø¬ÙØ© Ø§ÙØ®ÙÙÙØ©Ø Ø§ÙØ¢Ù ؚعد ØŽØ±ØØ§Ù Ù
ÙØ¬Ø²Ø§Ù." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "ÙÙ
Ù٠استخداÙ
ÙØ§ ØšÙØ§Ø³Ø·Ø© Ø£ØšØ§ØªØŽÙØ lighttpdØ ÙØªØ·ÙØš Ù
Ù٠اعدادÙÙ
, ÙÙÙ ÙÙØ³Øª Ù
ÙÙ
Ø© سÙÙØ© جداÙ." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "ÙÙ
ÙÙÙ Ø§ÙØØµÙ٠عÙÙØ© Ù
Ù ÙÙØ§ : https://github.com/jonashaag/bjoern, ÙÙ
ؚتجÙ
ÙØ¹Ø© ؚرÙ
Ø¬ÙØ§" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Ø§ÙØªØšØ§Ù: Ù٠ؚعض Ø§ÙØØ§ÙØ§Øª اÙÙØ§Ø¯Ø±Ø© Ø§ÙØ®Ø§Ø¯Ù
اÙÙ
دÙ
ج ÙØ§ ÙØ¹Ù
ÙØ إذا ÙØ§ØØžØª ÙØ¬Ùد Ù
؎اÙÙ Ù
ع ÙØ§Ø¬ÙØ© اÙÙÙØš" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "عد Ø¥ÙÙ ÙÙØ§ ÙÙÙ
ØšØªØºÙØ± Ø§ÙØ®Ø§Ø¯Ù
Ù
دÙ
ج ÙØ°Ø§Ù٠اÙÙ
ذÙÙØ± ÙÙØ§." + +#: module/setup.py:329 +msgid "Server" +msgstr "خادÙ
" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "# # إعداد SSL # #" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "تÙÙÙØ° ÙØ°Ù Ø§ÙØ£ÙاÙ
ر Ù
Ù Ù
Ø¬ÙØ¯ اعداد ؚا٠ÙÙØ¯ ÙØ§Ùتاج ØŽÙØ§Ø¯Ø§Øª ssl:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "اذا Ø§ÙØªÙÙØª ÙÙÙ ØŽÙØ¡ جر٠ؚ؎Ù٠صØÙØ, ØªØ³ØªØ·ÙØ¹ ØªÙØ¹ÙÙ ssl Ø§ÙØ§Ù." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "ØªÙØ¹ÙÙ SSLØ" + +#: module/setup.py:360 +msgid "Select action" +msgstr "ØØ¯Ø¯ Ø§ÙØ¥Ø¬Ø±Ø§Ø¡" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1-Ø¥ÙØŽØ§Ø¡/ØªØØ±Ùر اÙÙ
ستخدÙ
" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2-ÙØ§ØŠÙ
Ø© اÙÙ
ستخدÙ
ÙÙ" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3-Ø¥Ø²Ø§ÙØ© اÙÙ
ستخدÙ
" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4-Ø¥ÙÙØ§Ø¡" + +#: module/setup.py:376 +msgid "Users" +msgstr "اÙÙ
ستخدÙ
ÙÙ" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "اضغط Enter ÙÙØ¥ÙÙØ§Ø¡." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "ÙØŽÙ Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ Ù
سار Ø§ÙØªÙÙÙÙ: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "ÙÙÙ
Ø© اÙÙ
Ø±ÙØ±: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "ÙÙÙ
Ø© اÙÙ
Ø±ÙØ± ÙØµÙرة جداÙ. استخداÙ
4 رÙ
ÙØ² عÙÙ Ø§ÙØ§ÙÙ." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "ÙÙÙ
Ø© اÙÙ
Ø±ÙØ± (Ù
رة أخرÙ): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "ÙÙ
تتطاؚ٠ÙÙÙ
تا اÙÙ
Ø±ÙØ±." + +#: module/setup.py:493 +msgid "yes" +msgstr "ÙØ¹Ù
" + +#: module/setup.py:493 +msgid "true" +msgstr "صØÙØ" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "ÙØ§" + +#: module/setup.py:496 +msgid "false" +msgstr "خاط؊ة" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Ø§ÙØ¥Ø¯Ø®Ø§Ù ØºÙØ± ØµØ§ÙØ" + diff --git a/locale/bn/LC_MESSAGES/django.po b/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 000000000..9f320829d --- /dev/null +++ b/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Bengali\n" +"Language: bn_BD\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/bn/LC_MESSAGES/pyLoad.po b/locale/bn/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..002e93ad1 --- /dev/null +++ b/locale/bn/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Bengali\n" +"Language: bn_BD\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/bn/LC_MESSAGES/pyLoadCli.po b/locale/bn/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..945fc0276 --- /dev/null +++ b/locale/bn/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Bengali\n" +"Language: bn_BD\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/bn/LC_MESSAGES/setup.po b/locale/bn/LC_MESSAGES/setup.po new file mode 100644 index 000000000..da42f421a --- /dev/null +++ b/locale/bn/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Bengali\n" +"Language: bn_BD\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/ca/LC_MESSAGES/django.po b/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 000000000..2306240f8 --- /dev/null +++ b/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Catalan\n" +"Language: ca_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Sol·licitud d'un nou Captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Si us plau introdueixi el text que apareix al captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad ha estat reiniciat" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "apagat" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Ãxit" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "encÚs" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Estas segur que vols sortir del pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Reiniciar Enllaç" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Elimina enllaç" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Introdueixi el nom del paquet." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Clica a la posició correcta del captcha." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "S'ha produït un error." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "El directori és buit" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Ha fallat" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "No hi ha captchas per llegir." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Les contrasenyes no coincideixen." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Parà metres desats." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nou directori" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Estas segur que vols reiniciar pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "esperant %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Descà rregues actives" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Inici" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Descà rregues" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Registres" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Configuració" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Nom" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Estat" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Informació" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Mida" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Progrés" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Inici de sessió" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Nom d'usuari" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Contrasenya" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "El teu usuari d'usuari i contrasenya no concorden. Torna-ho a provar." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Per reiniciar les teves dades de login o afegir usuari executa:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Eliminar acabat" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Reiniciar fallit" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Carpeta:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Contrasenya:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Editar paquet" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Editar detalls del paquet segÃŒent." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Nom del paquet." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Carpeta" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Nom de la subcarpeta per aquestes descà rregues." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Llista de contrasenyes emprades per l'unrar." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Enviar" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Reiniciar" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Has tancat la sessió correctament." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Ruta" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absolut" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relatiu" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "nom" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "mida" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "tipus" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "última modificació" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "directori pare" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "sense contingut" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "General" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Comptes" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Tria una secció del menú" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Connector" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Và lid fins" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Trà fic restant" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Temps" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Max Paral·lel" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Eliminar?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "và lid" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "invà lid" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "sÃ" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Afegir" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Afegir compte" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Introdueix les dades del teu compte per emprar les caracterÃstiques premium." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "El seu nom d'usuari." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "La contrasenya és per aquest compte." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Tipus" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Tria proveïdor del teu compte." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Començar" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "anterior" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "segÃŒent" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Fi" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "NotÃcies" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Suport" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Sistema" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "S.O.:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "versió del pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Carpeta de instal·lació:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Carpeta de configuració:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Carpeta de descà rregues:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Espai lliure:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Idioma:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Port de la interfÃcie Web:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Port de la interfÃcie remota:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Configuració" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Gestor de Fitxers" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Afegir paquet" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Aferra els teus enllaços o puja un fitxer contenidor." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Nom del nou paquet." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Enllaços" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Aferra els teus enllaços aquó o qualsevol text i pitja el botó de filtrat." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtra urls" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Contrasenya per l'arxiu RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Fitxer" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Puja un contenidor." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Destinació" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Llegint captcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "El captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Introdueix el text del captcha." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Tancar" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "InterfÃcie web" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "Hi ha una actualització de pyLoad disponible!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins actualitzats, si us plau reinicia!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Esperant captcha" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Sortir" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrar" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Informació" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Si us plau fes login!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Aturar" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Cancel·lar" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Descà rrega:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Reconnectar:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Velocitat:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Actiu:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Recarregar pà gina" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "carregant" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Tornar a l'inici" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Sortir de pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Reiniciar pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Per afegir usuari o canviar contrasenya emprar:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Important: L'usuari administrador sempre te tots els permisos!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Canviar Contrasenya" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "Administrador" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Permisos" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "canviar" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Introdueixi la contrasenya actual i la desitjada." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Usuari" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Contrasenya actual" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Contrasenya nova" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "La nova contrasenya." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nova contrasenya (repetir)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Siusplau repeteix la nova contrasenya." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "No tens permisos per accedir a aquesta pà gina." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "No s'ha trobat el directori de descà rregues." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "il·limitat" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "no disponible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Executa pyload.py -s per accedir a l'instal·lació." + diff --git a/locale/ca/LC_MESSAGES/pyLoad.po b/locale/ca/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..5d58ff375 --- /dev/null +++ b/locale/ca/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Catalan\n" +"Language: ca_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "S'ha rebut la senyal de Sortida" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "ja s'estat executant pyLoad amb el pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Ha fallat el canvi de el grup: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Ha fallat el canvi d'usuari: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "carpeta de registre" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Començant" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Emprant el directori d'inici: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto descodificarà el contenidor de fitxers" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "carpeta per fitxers temporals" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "carpeta de descà rregues" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL per connexions segures" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Movent l'antiga configuració d'usuari a la DB" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Comprova les teves dades de login amb ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Tots els enllaços eliminats" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Temps de descà rrega: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Espai lliure: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Activant Comptes..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Activant Plugins..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad està en funcionament" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "reiniciant pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad està sortint" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Instal·la %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "no s'ha pogut trobar %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "no s'ha pogut crear %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "apagant..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "ha succeït un error mentre s'apagava" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "matat pyLoad des de el Terminal" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "L'arxiu de la base de dades ha estat eliminat per una incompatiblitat de la versió." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "El fitxer de la base de dades NO pot ser convertit." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "La base de dades ha estat convertida de la v2 a la v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "La base de dades ha estat convertida de la v3 a la v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Convertint l'antiga BD de Django" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "finalitzat" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "fora de lÃnia" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "en lÃnia" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "en cua" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "saltat" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "esperant" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "temporalment fora de lÃnia" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "començant" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "fallit" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "avortat" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "desxifrant" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "personalitzat" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "descarregant" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "processant" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "deconegut" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paquet finalitzat: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "Emprant SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Error al backend remot: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Iniciant %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "S'ha fallat la carrega del backend %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "esperant %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "No s'han trobat els certificats SSL." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Ho sent molt, ja no permetem iniciar %s directament emprant pyLoad" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Pots emprar el servidor amb fils que ofereix millor rendiment i ssl," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "per suposat encara pots emprar el teu %s amb el servidor fastcgi de pyLoad" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "les configuracions d'exemple estan al directori module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "No s'ha pogut emprar %(server)s, python-flup no està instal·lat!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Error important el servidor lleuger: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "Has de descarregar i compilar el bjoern. https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Copia el fitxer boern.so a la carpeta module/lib o empra setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Per suposat haurà s d'estar familiaritzat amb GNU/Linux i sabre com compilar programes" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "El servidor està en mode multi-fil degut als problemes de rendiment a windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Aquest servidor no ofereix SSL, si us plau considera l'opció d'emprar el servidor amb fils" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Iniciant el servidor incorporat: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Iniciant el servidor web SSL amb fils: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Iniciant el servidor web amb fils: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Iniciant el servidor fastcgi: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Iniciant el servidor web lleuger (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "No tens permisos per accedir a aquesta pà gina." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "No s'ha trobat el directori de descà rregues." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "il·limitat" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "no disponible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Executa pyload.py -s per accedir a l'instal·lació." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Descà rrega per trossos fallida, tornant a la connexió única | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Iniciant descà rrega: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Descà rrega finalitzada: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "El plugin %s troba a faltar una funció." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Descà rrega avortada: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Descà rrega reiniciada: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "La descà rrega està fora de lÃnia: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "La descà rrega està temporalment fora de lÃnia: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Descà rrega fallida: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "No s'ha pogut connectar amb el servidor o la connexió s'ha reiniciat, esperant 1 minuts per tornar-ho a provar." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Descà rrega omitida: %(name)s due to %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Desxifrant comença en: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Desxifrat fallit: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Re-intentant %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Obtenint informació per %(name)s failed | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Error executant ganxos: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "L'activació de %(name)s ha fallat" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Plugins activats: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Plugins desactivats: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Reconnexió fallida: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "No s'ha trobat l'script de reconnexió!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Iniciant reconnexió" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "L'execució de l'script de reconnexió ha fallat!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Reconnectat, nova IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "No queda suficient espai lliure al dispositiu" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "No s'ha pogut iniciar sessió amb el compte %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Contrasenya Errònia" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "L'hora %s està en un format incorrecte, empra: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "El compte %s no te suficient trà fic, es tornarà a comprovar d'aquà 30min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "El compte %s està caducat, es tornarà a comprovar d'aquà 1h" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "LÃmit de descà rrega assolit" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s té un patró invà lid." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Error important %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "No s'ha carregat cap proveïdor" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Activa la descà rrega directa al teu compte de Bitshare" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "LinkList no pot ser netejat." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Els ajustaments del compte han estat eliminats degut al nou format de la configuració." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Autorització requerida (usuari:contrasenya)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Si us plau, introdueixi el seu compte de %s o desactivar aquest plugin" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "Hi havia Codi HTML en el fitxer (%s) descarregat... error de re-direcció? Es re-iniciarà la descà rrega." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Fitxer temporalment no disponible" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: esperant entre descà rregues %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: esperant per captcha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "El fitxer descarregat estava buit" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "Clau de API invà lida" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: No queda suficient trà fic" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Trà fic excedit" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Trà fic Compartit (descà rrega directa)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Ja s'està descarregant des de aquesta adreça IP, esperant 60 segons" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Codi d'Autenticació invà lid, la descà rrega serà reiniciada" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: No hi ha espais lliures" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Necessites un compte premium per aquest fitxer" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Nom de fitxer informat invà lid" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Error de descà rrega paral·lela, esperant 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "No connectat." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Desxifrat ha fallat" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "Cap clau de fitxer proporcionat a la URL" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Codi d'error:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "El fitxer no existeix." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "* * * Plugins s'han actualitzat, si us plau reinicieu pyLoad * * *" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Plugins actualitzats i recarregats" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "No hi ha actualitzacions de plugins disponibles" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "No hi ha actualitzacions del pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** La nova Versió %s de pyLoad està disponible ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Obtengui'l aquÃ: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "No es pot connectar al servidor per actualitzacions" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nova versió de %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "S'ha produït un error mentre s'actualitzava %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "La versió no coincideix" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Descà rrega finalitzada: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nova petició de Captcha: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Constesta amb 'c %s text del captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "Si us plau, afegeiu el vostre compte premium.to i torneu a iniciar pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Afegit %s des de HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "El %s no està instal·lat" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "No s'ha pogut activar %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Activat" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "No hi han connectors d'extracció activats" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "El paquet %s s'ha posat a la cua per una posterior extracció" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Revisa el paquet %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Extreu a %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "No s'han trobat fitxers per extreure" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "extraient" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Protegit amb contrasenya" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Contrasenya incorrecta" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Eliminant els fitxers %s" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Extracció finalitzada" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Error d'arxiu" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "El CRC no coincideix" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Error desconegut" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Configuració d'usuari i el grup ha fallat" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: El Port 9666 ja s'està en ús" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s crÚdits restants" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "No s'ha pogut enviar la resposta." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "El teu compte de CaptchaTrader no te crÚdits suficients" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Llista de Crypter no trobada" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "La llista de Crypter està buida" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Descà rrega finalitzada : %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Nou CaptchaID de cà rrega: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "El teu compte de 9kw.eu no te crÚdits suficients" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Scripts instal·lats per %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Script no executable:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Error en %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "El teu compte de ExpertDecoders no te crÚdits suficients" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Si us plau afegir el seu compte de rehost.to primer i reinicieu pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "Si us plau afegiu un compte và lid premiumize.me primer i reinicieu pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d crÚdits restants" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil i tesseract no estan instal·lats i no hi ha cap Client connectat per desxifrar captchas" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Cap plugin ha pogut obtenir resultats apropiats d'aquest captcha en un temps assignat." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Aplicació d'Usuari i el Grup ha fallat: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "No hi ha cap client connectat per des-encriptar el captcha" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Afegit paquet %(name)s que conté les enllaços %(count)d" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Afegits %(count)d enllaços al paquet #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "No s'ha trobat cap motor js, si us plau instal·la Spidermonkey, ossp-js, pyv8 o rhino" + diff --git a/locale/ca/LC_MESSAGES/pyLoadCli.po b/locale/ca/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..995e05137 --- /dev/null +++ b/locale/ca/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Catalan\n" +"Language: ca_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " LÃnia de Comandes" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s Baixades:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Velocitat: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Mida: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Acabarà en: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "esperant: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Estat:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "pausat" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "executant" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "velocitat Total" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Fitxers en cua" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Menú:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Afegeix enllaços" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Gestiona Cua" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " Gestiona Col·lector" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "ReprÚn/Pausa Servidor" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Mata Servidor" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Surt" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Si us plau empreu aquesta sintaxi: add <Package name> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Comprovant %d enllaç(os):" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "El fitxer no existeix." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad ha finalitzat" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Mostra estat del servidor" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Mostra descà rregues en cua" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Mostra descà rreges en el col·lector" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Afegeix paquet a la cua" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Afegeix paquet al col·lector" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Elimina Fitxers de la Cua/Col·lector" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Elimina Paquets de la Cua/Col·lector" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Mou Paquets de la Cua al Col·lector o viceversa" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Reinicia fitxers" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Reinicia paquets" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Comprova l'estat online, funciona amb contenidor local" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Comprova l'estat online d'un fitxer contenidor" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Pausa el servidor" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "continua les descà rregues" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Canvia pausa/reprÚn" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "mata servidor" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Llista de comandes:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "No s'ha pogut escriure el fitxer de configuració d'usuari" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Necessites py-openssl per connectar-te al nucli del pyLoad." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adreça: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Nom d'usuari: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Contrasenya: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Dades d'accés incorrectes." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "No s'ha pogut establir la connexió a %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Necessites py-openssl per connectar-te al nucli del pyLoad." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Mode interactiu ignorat ja que has especificat algunes comandes." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Afegeix Paquet:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Introdueix el nom per el nou paquet" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Paquet: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Analitza dels enllaços que vols introduir." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Introdueix %s en acabar." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Enllaços afegits: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " torna al menú principal" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Gestiona Paquets:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Gestiona Enllaços:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "QuÚ vols moure?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "QuÚ vols eliminar?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "QuÚ vols reiniciar?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Tria el que vols fer o introdueix un número de paquet." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "elimina" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "mou" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "reinicia" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - anterior" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - segÃŒent" + diff --git a/locale/ca/LC_MESSAGES/setup.po b/locale/ca/LC_MESSAGES/setup.po new file mode 100644 index 000000000..0ad9ba08a --- /dev/null +++ b/locale/ca/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Catalan\n" +"Language: ca_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "s" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Benvingut a l'Assistent de Configuració de pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Es comprovarà el teu equip i es farà una configuració bà sica per executar pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "El valor entre claudà tors [] sempre és el valor per defecte," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "en cas de no voler canviar-ho o si estas insegur de que triar simplement pitja enter." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "No oblidis: Sempre pots tornar a l'assistent amb els parà metres --setup o -s quan inicies el pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Si tens cap problema amb l'assistent pitja Control-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "per avortar i no permetre que s'iniciï automà ticament amb pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Quan estiguis llest per la comprovació del sistema pitja enter." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Necessites pycurl, squlit i python 2.5, 2.6 o 2.7 per executar pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Si us plau corregeix aixo i torna a executar el pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "L'assistent ara es tancarà ." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "La comprovació del sistema ha acabat, pitja enter per veure l'informe de l'estat." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Estat ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "desxifrant contenidor" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "connexió SSL" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "desxifrat automà tic de captcha" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "InterfÃcie web" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "extensió Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "Funcionalitats disponibles:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Funcionalitats no disponibles: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crytop no disponible" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Això es necessari si vols desxifrar els contenidors de fitxers." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL no disponible" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Això es necessari si vols establir connexions segures amb el nucli o la interfÃcie web." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Si només voleu accedir a pyLoad localment el SSL no és necessari." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "reconeixedor de Captchas no disponible" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Només necessari per alguns proveïdors com a usuari gratuït." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "GUI no disponible" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "La InterfÃcie Grà fica d'Usuari." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "no s'ha trobat el motor JavaScript" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Es necessari algun d'aquests paquets per els enllaços Click'N'Load. Instal.la Spidermonkey, ossp-js, pyv8 o rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Ara pots avortar la instal·lació i arreglar les dependÚncies, si aixà ho prefereixes." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Continuar amb la instal·lació?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Vols canviar la ruta de configuració? Actualment és %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Si estas emprant pyLoad en un servidor o en una partició a un dispositiu flash intern és una bona idea canviar-ho." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Canviar la ruta de configuració?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Vols configurar les dades d'accés i la configuració bà sica?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Això és recomanant en la primera execució." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Establir una configuració bà sica?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Vols configurar el SSL?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Configurar SSL?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Vols configurar l'interÃicie web?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Configurar interfÃcie web?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Configuració finalitzada satisfactòriament." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Pitja enter i reinicia pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Comprovació del Sistema ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "La teva versió de python és massa nova. Si us plau empra Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "La teva versió de python és massa antiga. Si us plau empra com a mÃnim Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Versió de Python: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "La teva versió %s de jinja2 es massa antiga." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Pots continuar tranquil·lament encara que la interfÃcie web no funcioni," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "si us plau actualitza o desinstal·la-ho, pylLoad ja inclou una biblioteca jinja2." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "Motor JS" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Configuració bà sica ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Les dades d'accés segÃŒents són và lides per CLI, GUI i la interfÃcie web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Nom d'usuari" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Els clients externs (GUI, CLI i altres) necessiten accés remot a través de la xarxa per funcionar." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "No obstant, si només vos emprar la interfÃcie web pots deshabilitar-lo per estalviar memòria ram." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Activar accés remot" + +#: module/setup.py:291 +msgid "Language" +msgstr "Idioma" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Directori de descà rregues" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Nombre mà xim de descà rregues paral·leles" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Emprar el reconnectar?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Ubicació de l'script de reconnexió" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Configuració de la interfÃcie Web ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Activar interfÃcie web?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Adreça d'escolta, si empres 127.0.0.1 o localhost la interfÃcie web només serà accessible localment." + +#: module/setup.py:312 +msgid "Address" +msgstr "Adreça" + +#: module/setup.py:313 +msgid "Port" +msgstr "Port" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad ofereix uns quants backends, ara se'n farà una breu explicació." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "El servidor per defecte es la millor opció si no saps quin triar." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Aquest servidor ofereix SSL i es una bona alternativa a l'integrat." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Pots emprar apache, lighttpd, però requereixen ser configurats i no sempre és una tasca fà cil." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Una alternativa escrita en C, requereix libev i coneixements de GNU/Linux." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Aconsegueix-lo aquÃ: https://github.com/jonashaag/bjoern, compila'l" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "i copia bjoren.so a module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Atenció: En alguns casos estranys el servidor integrat no funciona, ho notareu amb problemes a la interfÃcie web" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "torna aquà i canvia el servidor integrat per el servidor amb fils." + +#: module/setup.py:329 +msgid "Server" +msgstr "Servidor" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Configuració SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Executa aquesta comanada des de la carpeta de configuració de pyLoad per fer els certificats SSL:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Si has acabat i tot ha anat bé ara podrà s activar el SSL." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "Activar SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Tria una opció" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Crear/editar usuari" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Llistar usuaris" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Eliminar usuari" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Sortir" + +#: module/setup.py:376 +msgid "Users" +msgstr "Usuaris" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Configurant nova ruta de configuració, la configuració actual no serà transferida!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Ruta de configuració" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Ruta de configuració canviada, la instal·lació es tancarà , si us plau reinicia per continuar." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Pitja enter per sortir." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "L'ajustament de la ruta de configuració ha fallat: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: perdut" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Contrasenya: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "La contrasenya és massa curta. Utilitzeu almenys 4 carà cters." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Contrasenya (altre cop): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Les contrasenyes no coincideixen." + +#: module/setup.py:493 +msgid "yes" +msgstr "sÃ" + +#: module/setup.py:493 +msgid "true" +msgstr "cert" + +#: module/setup.py:493 +msgid "t" +msgstr "c" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "fals" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Entrada invà lida" + diff --git a/locale/cli.pot b/locale/cli.pot index 646c6c70e..e6cd0a1e3 100644 --- a/locale/cli.pot +++ b/locale/cli.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: pyLoad 0.4.9\n" +"Project-Id-Version: pyLoad 0.4.10\n" "Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" -"POT-Creation-Date: 2011-12-07 19:21+0100\n" +"POT-Creation-Date: 2014-07-13 20:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,213 +17,243 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: pyLoadCli.py:75 pyLoadCli.py:133 +#: module/cli/Cli.py:75 module/cli/Cli.py:133 msgid " Command Line Interface" msgstr "" -#: pyLoadCli.py:165 +#: module/cli/Cli.py:165 #, python-format msgid "%s Downloads:" msgstr "" -#: pyLoadCli.py:177 +#: module/cli/Cli.py:177 msgid " Speed: " msgstr "" -#: pyLoadCli.py:177 +#: module/cli/Cli.py:177 msgid " Size: " msgstr "" -#: pyLoadCli.py:178 +#: module/cli/Cli.py:178 msgid " Finished in: " msgstr "" -#: pyLoadCli.py:179 +#: module/cli/Cli.py:179 msgid " ID: " msgstr "" -#: pyLoadCli.py:184 +#: module/cli/Cli.py:184 msgid "waiting: " msgstr "" -#: pyLoadCli.py:191 pyLoadCli.py:193 +#: module/cli/Cli.py:191 module/cli/Cli.py:193 msgid "Status:" msgstr "" -#: pyLoadCli.py:191 +#: module/cli/Cli.py:191 msgid "paused" msgstr "" -#: pyLoadCli.py:193 +#: module/cli/Cli.py:193 msgid "running" msgstr "" -#: pyLoadCli.py:196 +#: module/cli/Cli.py:196 msgid "total Speed" msgstr "" -#: pyLoadCli.py:196 +#: module/cli/Cli.py:196 msgid "Files in queue" msgstr "" -#: pyLoadCli.py:197 +#: module/cli/Cli.py:197 msgid "Total" msgstr "" -#: pyLoadCli.py:203 +#: module/cli/Cli.py:203 msgid "Menu:" msgstr "" -#: pyLoadCli.py:205 +#: module/cli/Cli.py:205 msgid " Add Links" msgstr "" -#: pyLoadCli.py:206 +#: module/cli/Cli.py:206 msgid " Manage Queue" msgstr "" -#: pyLoadCli.py:207 +#: module/cli/Cli.py:207 msgid " Manage Collector" msgstr "" -#: pyLoadCli.py:208 +#: module/cli/Cli.py:208 msgid " (Un)Pause Server" msgstr "" -#: pyLoadCli.py:209 +#: module/cli/Cli.py:209 msgid " Kill Server" msgstr "" -#: pyLoadCli.py:210 +#: module/cli/Cli.py:210 msgid " Quit" msgstr "" -#: pyLoadCli.py:289 pyLoadCli.py:296 +#: module/cli/Cli.py:289 module/cli/Cli.py:296 msgid "Please use this syntax: add <Package name> <link> <link2> ..." msgstr "" -#: pyLoadCli.py:315 +#: module/cli/Cli.py:315 #, python-format msgid "Checking %d links:" msgstr "" -#: pyLoadCli.py:324 +#: module/cli/Cli.py:324 msgid "File does not exists." msgstr "" -#: pyLoadCli.py:385 +#: module/cli/Cli.py:385 msgid "pyLoad was terminated" msgstr "" -#: pyLoadCli.py:443 +#: module/cli/Cli.py:443 msgid "Prints server status" msgstr "" -#: pyLoadCli.py:444 +#: module/cli/Cli.py:444 msgid "Prints downloads in queue" msgstr "" -#: pyLoadCli.py:445 +#: module/cli/Cli.py:445 msgid "Prints downloads in collector" msgstr "" -#: pyLoadCli.py:446 +#: module/cli/Cli.py:446 msgid "Adds package to queue" msgstr "" -#: pyLoadCli.py:447 +#: module/cli/Cli.py:447 msgid "Adds package to collector" msgstr "" -#: pyLoadCli.py:448 +#: module/cli/Cli.py:448 msgid "Delete Files from Queue/Collector" msgstr "" -#: pyLoadCli.py:449 +#: module/cli/Cli.py:449 msgid "Delete Packages from Queue/Collector" msgstr "" -#: pyLoadCli.py:450 +#: module/cli/Cli.py:450 msgid "Move Packages from Queue to Collector or vice versa" msgstr "" -#: pyLoadCli.py:451 +#: module/cli/Cli.py:451 msgid "Restart files" msgstr "" -#: pyLoadCli.py:452 +#: module/cli/Cli.py:452 msgid "Restart packages" msgstr "" -#: pyLoadCli.py:453 +#: module/cli/Cli.py:453 msgid "Check online status, works with local container" msgstr "" -#: pyLoadCli.py:454 +#: module/cli/Cli.py:454 msgid "Checks online status of a container file" msgstr "" -#: pyLoadCli.py:455 +#: module/cli/Cli.py:455 msgid "Pause the server" msgstr "" -#: pyLoadCli.py:456 +#: module/cli/Cli.py:456 msgid "continue downloads" msgstr "" -#: pyLoadCli.py:457 +#: module/cli/Cli.py:457 msgid "Toggle pause/unpause" msgstr "" -#: pyLoadCli.py:458 +#: module/cli/Cli.py:458 msgid "kill server" msgstr "" -#: pyLoadCli.py:460 +#: module/cli/Cli.py:460 msgid "List of commands:" msgstr "" -#: pyLoadCli.py:473 +#: module/cli/Cli.py:473 msgid "Couldn't write user config file" msgstr "" -#: pyLoadCli.py:548 +#: module/cli/Cli.py:548 msgid "You need py-openssl to connect to this pyLoad Core." msgstr "" -#: pyLoadCli.py:555 +#: module/cli/Cli.py:555 msgid "Address: " msgstr "" -#: pyLoadCli.py:556 +#: module/cli/Cli.py:556 msgid "Port: " msgstr "" -#: pyLoadCli.py:557 +#: module/cli/Cli.py:557 msgid "Username: " msgstr "" -#: pyLoadCli.py:561 +#: module/cli/Cli.py:561 msgid "Password: " msgstr "" -#: pyLoadCli.py:566 pyLoadCli.py:575 +#: module/cli/Cli.py:566 module/cli/Cli.py:575 msgid "Login data is wrong." msgstr "" -#: pyLoadCli.py:568 pyLoadCli.py:577 +#: module/cli/Cli.py:568 module/cli/Cli.py:577 #, python-format msgid "Could not establish connection to %(addr)s:%(port)s." msgstr "" -#: pyLoadCli.py:580 +#: module/cli/Cli.py:580 msgid "You need py-openssl to connect to this pyLoad core." msgstr "" -#: pyLoadCli.py:582 +#: module/cli/Cli.py:582 msgid "Interactive mode ignored since you passed some commands." msgstr "" +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + #: module/cli/ManageFiles.py:97 msgid "Manage Packages:" msgstr "" @@ -267,33 +297,3 @@ msgstr "" #: module/cli/ManageFiles.py:148 msgid " - next" msgstr "" - -#: module/cli/ManageFiles.py:149 module/cli/AddPackage.py:64 -msgid " back to main menu" -msgstr "" - -#: module/cli/AddPackage.py:48 -msgid "Add Package:" -msgstr "" - -#: module/cli/AddPackage.py:53 -msgid "Enter a name for the new package" -msgstr "" - -#: module/cli/AddPackage.py:57 -#, python-format -msgid "Package: %s" -msgstr "" - -#: module/cli/AddPackage.py:58 -msgid "Parse the links you want to add." -msgstr "" - -#: module/cli/AddPackage.py:59 -#, python-format -msgid "Type %s when done." -msgstr "" - -#: module/cli/AddPackage.py:60 -msgid "Links added: " -msgstr "" diff --git a/locale/core.pot b/locale/core.pot index 546f0e4d3..177ac109c 100644 --- a/locale/core.pot +++ b/locale/core.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: pyLoad 0.4.9\n" +"Project-Id-Version: pyLoad 0.4.10\n" "Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" -"POT-Creation-Date: 2011-12-07 19:21+0100\n" +"POT-Creation-Date: 2014-07-13 20:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,567 +17,581 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: pyLoadCore.py:185 +#: module/Core.py:181 msgid "Received Quit signal" msgstr "" -#: pyLoadCore.py:301 +#: module/Core.py:302 #, python-format msgid "pyLoad already running with pid %s" msgstr "" -#: pyLoadCore.py:315 +#: module/Core.py:316 #, python-format msgid "Failed changing group: %s" msgstr "" -#: pyLoadCore.py:325 +#: module/Core.py:326 #, python-format msgid "Failed changing user: %s" msgstr "" -#: pyLoadCore.py:327 +#: module/Core.py:328 msgid "folder for logs" msgstr "" -#: pyLoadCore.py:338 +#: module/Core.py:339 msgid "Starting" msgstr "" -#: pyLoadCore.py:339 +#: module/Core.py:340 #, python-format msgid "Using home directory: %s" msgstr "" -#: pyLoadCore.py:348 +#: module/Core.py:349 msgid "pycrypto to decode container files" msgstr "" -#: pyLoadCore.py:351 +#: module/Core.py:352 msgid "folder for temporary files" msgstr "" -#: pyLoadCore.py:356 +#: module/Core.py:357 msgid "folder for downloads" msgstr "" -#: pyLoadCore.py:359 +#: module/Core.py:360 msgid "OpenSSL for secure connection" msgstr "" -#: pyLoadCore.py:363 +#: module/Core.py:364 msgid "Moving old user config to DB" msgstr "" -#: pyLoadCore.py:366 -msgid "Please check your logindata with ./pyLoadCore.py -u" +#: module/Core.py:367 +msgid "Please check your logindata with ./pyload.py -u" msgstr "" -#: pyLoadCore.py:369 +#: module/Core.py:370 msgid "All links removed" msgstr "" -#: pyLoadCore.py:400 +#: module/Core.py:401 #, python-format msgid "Downloadtime: %s" msgstr "" -#: pyLoadCore.py:410 +#: module/Core.py:411 #, python-format msgid "Free space: %s" msgstr "" -#: pyLoadCore.py:430 +#: module/Core.py:431 msgid "Activating Accounts..." msgstr "" -#: pyLoadCore.py:436 +#: module/Core.py:437 msgid "Activating Plugins..." msgstr "" -#: pyLoadCore.py:439 +#: module/Core.py:440 msgid "pyLoad is up and running" msgstr "" -#: pyLoadCore.py:458 +#: module/Core.py:459 msgid "restarting pyLoad" msgstr "" -#: pyLoadCore.py:462 +#: module/Core.py:463 msgid "pyLoad quits" msgstr "" -#: pyLoadCore.py:519 +#: module/Core.py:520 #, python-format msgid "Install %s" msgstr "" -#: pyLoadCore.py:555 +#: module/Core.py:556 #, python-format msgid "could not find %(desc)s: %(name)s" msgstr "" -#: pyLoadCore.py:557 +#: module/Core.py:558 #, python-format msgid "could not create %(desc)s: %(name)s" msgstr "" -#: pyLoadCore.py:578 +#: module/Core.py:579 msgid "shutting down..." msgstr "" -#: pyLoadCore.py:595 +#: module/Core.py:596 msgid "error while shutting down" msgstr "" -#: pyLoadCore.py:659 +#: module/Core.py:660 msgid "killed pyLoad from Terminal" msgstr "" -#: module/common/JsEngine.py:156 -msgid "" -"No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or " -"rhino" +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." msgstr "" -#: module/remote/ThriftBackend.py:39 -msgid "Using SSL ThriftBackend" +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." msgstr "" -#: module/remote/RemoteManager.py:35 -#, python-format -msgid "Remote backend error: %s" +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." msgstr "" -#: module/remote/RemoteManager.py:82 -#, python-format -msgid "Starting %(name)s: %(addr)s:%(port)s" +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." msgstr "" -#: module/remote/RemoteManager.py:84 -#, python-format -msgid "Failed loading backend %(name)s | %(error)s" +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" msgstr "" -#: module/ThreadManager.py:137 -#, python-format -msgid "Reconnect Failed: %s" +#: module/database/FileDatabase.py:45 +msgid "finished" msgstr "" -#: module/ThreadManager.py:176 -msgid "Reconnect script not found!" +#: module/database/FileDatabase.py:45 +msgid "offline" msgstr "" -#: module/ThreadManager.py:182 -msgid "Starting reconnect" +#: module/database/FileDatabase.py:45 +msgid "online" msgstr "" -#: module/ThreadManager.py:196 -msgid "Failed executing reconnect script!" +#: module/database/FileDatabase.py:45 +msgid "queued" msgstr "" -#: module/ThreadManager.py:208 -#, python-format -msgid "Reconnected, new IP: %s" +#: module/database/FileDatabase.py:45 +msgid "skipped" msgstr "" -#: module/ThreadManager.py:288 -msgid "Not enough space left on device" +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" msgstr "" -#: module/HookManager.py:90 module/plugins/Hook.py:102 +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 #, python-format -msgid "Error executing hooks: %s" +msgid "Package finished: %s" msgstr "" -#: module/HookManager.py:140 +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 #, python-format -msgid "Failed activating %(name)s" +msgid "Remote backend error: %s" msgstr "" -#: module/HookManager.py:144 +#: module/remote/RemoteManager.py:82 #, python-format -msgid "Activated plugins: %s" +msgid "Starting %(name)s: %(addr)s:%(port)s" msgstr "" -#: module/HookManager.py:145 +#: module/remote/RemoteManager.py:84 #, python-format -msgid "Deactivate plugins: %s" +msgid "Failed loading backend %(name)s | %(error)s" msgstr "" -#: module/CaptchaManager.py:78 module/interaction/InteractionManager.py:82 -msgid "No Client connected for captcha decrypting" +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" msgstr "" -#: module/web/ServerThread.py:35 +#: module/threads/ServerThread.py:36 msgid "SSL certificates not found." msgstr "" -#: module/web/ServerThread.py:39 +#: module/threads/ServerThread.py:40 #, python-format msgid "Sorry, we dropped support for starting %s directly within pyLoad" msgstr "" -#: module/web/ServerThread.py:40 +#: module/threads/ServerThread.py:41 msgid "You can use the threaded server which offers good performance and ssl," msgstr "" -#: module/web/ServerThread.py:41 +#: module/threads/ServerThread.py:42 #, python-format msgid "" "of course you can still use your existing %s with pyLoads fastcgi server" msgstr "" -#: module/web/ServerThread.py:42 -msgid "sample configs are located in the module/web/servers directory" +#: module/threads/ServerThread.py:43 +msgid "sample configs are located in the module/webui/servers directory" msgstr "" -#: module/web/ServerThread.py:49 +#: module/threads/ServerThread.py:49 #, python-format msgid "Can't use %(server)s, python-flup is not installed!" msgstr "" -#: module/web/ServerThread.py:56 +#: module/threads/ServerThread.py:58 #, python-format msgid "Error importing lightweight server: %s" msgstr "" -#: module/web/ServerThread.py:57 +#: module/threads/ServerThread.py:59 msgid "" "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" msgstr "" -#: module/web/ServerThread.py:58 +#: module/threads/ServerThread.py:60 msgid "Copy the boern.so to module/lib folder or use setup.py install" msgstr "" -#: module/web/ServerThread.py:59 +#: module/threads/ServerThread.py:61 msgid "" "Of course you need to be familiar with linux and know how to compile software" msgstr "" -#: module/web/ServerThread.py:63 +#: module/threads/ServerThread.py:64 msgid "Server set to threaded, due to known performance problems on windows." msgstr "" -#: module/web/ServerThread.py:80 module/web/ServerThread.py:103 +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 msgid "This server offers no SSL, please consider using threaded instead" msgstr "" -#: module/web/ServerThread.py:82 +#: module/threads/ServerThread.py:82 #, python-format msgid "Starting builtin webserver: %(host)s:%(port)d" msgstr "" -#: module/web/ServerThread.py:87 +#: module/threads/ServerThread.py:87 #, python-format msgid "Starting threaded SSL webserver: %(host)s:%(port)d" msgstr "" -#: module/web/ServerThread.py:91 +#: module/threads/ServerThread.py:91 #, python-format msgid "Starting threaded webserver: %(host)s:%(port)d" msgstr "" -#: module/web/ServerThread.py:97 +#: module/threads/ServerThread.py:97 #, python-format msgid "Starting fastcgi server: %(host)s:%(port)d" msgstr "" -#: module/web/ServerThread.py:105 +#: module/threads/ServerThread.py:105 #, python-format msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" msgstr "" -#: module/web/pyload_app.py:125 +#: module/webui/app/pyload.py:127 msgid "You dont have permission to access this page." msgstr "" -#: module/web/pyload_app.py:193 +#: module/webui/app/pyload.py:195 msgid "Download directory not found." msgstr "" -#: module/web/pyload_app.py:260 module/web/pyload_app.py:267 +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 msgid "unlimited" msgstr "" -#: module/web/pyload_app.py:262 module/web/pyload_app.py:269 +#: module/webui/app/pyload.py:264 module/webui/app/pyload.py:271 msgid "not available" msgstr "" -#: module/web/pyload_app.py:509 -msgid "Run pyLoadCore.py -s to access the setup." +#: module/webui/app/pyload.py:509 +msgid "Run pyload.py -s to access the setup." msgstr "" -#: module/web/json_app.py:60 +#: module/network/HTTPDownload.py:245 #, python-format -msgid "waiting %s" +msgid "Download chunks failed, fallback to single connection | %s" msgstr "" -#: module/Api.py:329 +#: module/threads/PluginThread.py:183 #, python-format -msgid "Added package %(name)s containing %(count)d links" +msgid "Download starts: %s" msgstr "" -#: module/Api.py:592 +#: module/threads/PluginThread.py:189 #, python-format -msgid "Added %(count)d links to package #%(package)d " -msgstr "" - -#: module/plugins/crypter/SerienjunkiesOrg.py:125 -msgid "Downloadlimit reached" -msgstr "" - -#: module/plugins/hooks/ClickAndLoad.py:74 -msgid "Click'N'Load: Port 9666 already in use" +msgid "Download finished: %s" msgstr "" -#: module/plugins/hooks/ExtractArchive.py:91 +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 #, python-format -msgid "No %s installed" +msgid "Plugin %s is missing a function." msgstr "" -#: module/plugins/hooks/ExtractArchive.py:93 -#: module/plugins/hooks/ExtractArchive.py:98 +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 #, python-format -msgid "Could not activate %s" -msgstr "" - -#: module/plugins/hooks/ExtractArchive.py:103 -msgid "Activated" -msgstr "" - -#: module/plugins/hooks/ExtractArchive.py:105 -msgid "No Extract plugins activated" +msgid "Download aborted: %s" msgstr "" -#: module/plugins/hooks/ExtractArchive.py:117 +#: module/threads/PluginThread.py:222 #, python-format -msgid "Package %s queued for later extracting" +msgid "Download restarted: %(name)s | %(msg)s" msgstr "" -#: module/plugins/hooks/ExtractArchive.py:142 +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 #, python-format -msgid "Check package %s" +msgid "Download is offline: %s" msgstr "" -#: module/plugins/hooks/ExtractArchive.py:179 +#: module/threads/PluginThread.py:234 #, python-format -msgid "Extract to %s" -msgstr "" - -#: module/plugins/hooks/ExtractArchive.py:198 -msgid "extracting" -msgstr "" - -#: module/plugins/hooks/ExtractArchive.py:209 -msgid "Password protected" -msgstr "" - -#: module/plugins/hooks/ExtractArchive.py:229 -msgid "Wrong password" +msgid "Download is temporary offline: %s" msgstr "" -#: module/plugins/hooks/ExtractArchive.py:237 +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 #, python-format -msgid "Deleting %s files" -msgstr "" - -#: module/plugins/hooks/ExtractArchive.py:242 -msgid "Extracting finished" -msgstr "" - -#: module/plugins/hooks/ExtractArchive.py:249 -msgid "Archive Error" +msgid "Download failed: %(name)s | %(msg)s" msgstr "" -#: module/plugins/hooks/ExtractArchive.py:251 -msgid "CRC Mismatch" +#: module/threads/PluginThread.py:254 +msgid "" +"Couldn't connect to host or connection reset, waiting 1 minute and retry." msgstr "" -#: module/plugins/hooks/ExtractArchive.py:255 -msgid "Unknown Error" +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" msgstr "" -#: module/plugins/hooks/ExtractArchive.py:307 -msgid "Setting User and Group failed" +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" msgstr "" -#: module/plugins/hooks/CaptchaTrader.py:71 +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 #, python-format -msgid "%s credits left" +msgid "Decrypting failed: %(name)s | %(msg)s" msgstr "" -#: module/plugins/hooks/CaptchaTrader.py:132 -msgid "Your CaptchaTrader Account has not enough credits" +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" msgstr "" -#: module/plugins/hooks/IRCInterface.py:74 -#: module/plugins/hooks/XMPPInterface.py:82 -#: module/database/FileDatabase.py:507 +#: module/threads/PluginThread.py:635 #, python-format -msgid "Package finished: %s" +msgid "Info Fetching for %(name)s failed | %(err)s" msgstr "" -#: module/plugins/hooks/IRCInterface.py:81 +#: module/HookManager.py:90 module/plugins/Hook.py:103 #, python-format -msgid "Download finished: %(name)s @ %(plugin)s " +msgid "Error executing hooks: %s" msgstr "" -#: module/plugins/hooks/IRCInterface.py:93 +#: module/HookManager.py:140 #, python-format -msgid "New Captcha Request: %s" +msgid "Failed activating %(name)s" msgstr "" -#: module/plugins/hooks/IRCInterface.py:94 +#: module/HookManager.py:144 #, python-format -msgid "Answer with 'c %s text on the captcha'" +msgid "Activated plugins: %s" msgstr "" -#: module/plugins/hooks/XMPPInterface.py:90 +#: module/HookManager.py:145 #, python-format -msgid "Download finished: %(name)s @ %(plugin)s" +msgid "Deactivate plugins: %s" msgstr "" -#: module/plugins/hooks/RehostTo.py:32 -msgid "Please add your rehost.to account first and restart pyLoad" +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" msgstr "" -#: module/plugins/hooks/HotFolder.py:82 -#, python-format -msgid "Added %s from HotFolder" +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" msgstr "" -#: module/plugins/hooks/ExternalScripts.py:54 -#, python-format -msgid "Installed scripts for %s: " +#: module/ThreadManager.py:182 +msgid "Starting reconnect" msgstr "" -#: module/plugins/hooks/ExternalScripts.py:70 -msgid "Script not executable:" +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" msgstr "" -#: module/plugins/hooks/ExternalScripts.py:80 +#: module/ThreadManager.py:208 #, python-format -msgid "Error in %(script)s: %(error)s" +msgid "Reconnected, new IP: %s" msgstr "" -#: module/plugins/hooks/UpdateManager.py:68 -msgid "No Updates for pyLoad" +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" msgstr "" -#: module/plugins/hooks/UpdateManager.py:73 -msgid "*** Plugins have been updated, please restart pyLoad ***" +#: module/plugins/Account.py:85 module/plugins/Account.py:90 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" msgstr "" -#: module/plugins/hooks/UpdateManager.py:75 -msgid "Plugins updated and reloaded" +#: module/plugins/Account.py:86 +msgid "Wrong Password" msgstr "" -#: module/plugins/hooks/UpdateManager.py:78 -msgid "No plugin updates available" +#: module/plugins/Account.py:243 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" msgstr "" -#: module/plugins/hooks/UpdateManager.py:93 +#: module/plugins/Account.py:269 #, python-format -msgid "*** New pyLoad Version %s available ***" +msgid "Account %s has not enough traffic, checking again in 30min" msgstr "" -#: module/plugins/hooks/UpdateManager.py:94 -msgid "*** Get it here: http://pyload.org/download ***" +#: module/plugins/Account.py:276 +#, python-format +msgid "Account %s is expired, checking again in 1h" msgstr "" -#: module/plugins/hooks/UpdateManager.py:97 -#: module/plugins/hooks/UpdateManager.py:110 -msgid "Not able to connect server for updates" +#: module/plugins/crypter/SerienjunkiesOrg.py:126 +msgid "Downloadlimit reached" msgstr "" -#: module/plugins/hooks/UpdateManager.py:141 +#: module/plugins/PluginManager.py:153 #, python-format -msgid "New version of %(type)s|%(name)s : %(version).2f" +msgid "%s has a invalid pattern." msgstr "" -#: module/plugins/hooks/UpdateManager.py:150 -#: module/plugins/hooks/UpdateManager.py:155 +#: module/plugins/PluginManager.py:272 #, python-format -msgid "Error when updating %s" +msgid "Error importing %(name)s: %(msg)s" msgstr "" -#: module/plugins/hooks/UpdateManager.py:155 -msgid "Version mismatch" +#: module/plugins/internal/MultiHoster.py:132 +msgid "No Hoster loaded" msgstr "" -#: module/plugins/hoster/BasePlugin.py:53 -msgid "Authorization required (username:password)" +#: module/plugins/accounts/BitshareCom.py:38 +msgid "Activate direct Download in your Bitshare Account" msgstr "" -#: module/plugins/hoster/OronCom.py:135 -msgid "Not enough traffic left" +#: module/plugins/container/LinkList.py:64 +msgid "LinkList could not be cleared." msgstr "" -#: module/plugins/hoster/OronCom.py:137 -#: module/plugins/hoster/UploadedTo.py:158 -msgid "Traffic exceeded" +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." msgstr "" -#: module/plugins/hoster/MegauploadCom.py:135 -msgid "You should enable direct Download in your Megaupload Account settings" +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" msgstr "" -#: module/plugins/hoster/MegauploadCom.py:158 +#: module/plugins/hoster/SimplydebridCom.py:23 +#: module/plugins/hoster/RealdebridCom.py:40 +#: module/plugins/hoster/FreeWayMe.py:39 module/plugins/hoster/ZeveraCom.py:21 +#: module/plugins/hoster/UnrestrictLi.py:52 +#: module/plugins/hoster/Vipleech4uCom.py:30 +#: module/plugins/hoster/Premium4Me.py:27 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/SimplyPremiumCom.py:52 +#: module/plugins/hoster/MegaDebridEu.py:46 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/LinksnappyCom.py:29 +#: module/plugins/hoster/DebridItaliaCom.py:39 +#: module/plugins/hoster/RPNetBiz.py:28 +#: module/plugins/hoster/MultiDebridCom.py:40 +#: module/plugins/hoster/ReloadCc.py:26 module/plugins/hoster/OverLoadMe.py:38 +#: module/plugins/hoster/RehostTo.py:25 +#: module/plugins/hoster/PremiumizeMe.py:24 +#: module/plugins/hooks/RPNetBiz.py:45 #, python-format -msgid "Megaupload: waiting %d minutes" -msgstr "" - -#: module/plugins/hoster/MegauploadCom.py:172 -msgid "You need premium to download files larger than 1 GB" +msgid "Please enter your %s account or deactivate this plugin" msgstr "" -#: module/plugins/hoster/MegauploadCom.py:177 -msgid "The file is password protected, enter a password and restart." +#: module/plugins/hoster/FilesMailRu.py:98 +#, python-format +msgid "" +"There was HTML Code in the Downloaded File (%s)...redirect error? The " +"Download will be restarted." msgstr "" -#: module/plugins/hoster/MegauploadCom.py:194 -msgid "Megaupload is currently blocking your IP. Try again later, manually." +#: module/plugins/hoster/NetloadIn.py:145 +#: module/plugins/hoster/NetloadIn.py:169 +msgid "File temporarily not available" msgstr "" -#: module/plugins/hoster/MegauploadCom.py:269 -msgid "" -"Looks like the file is still not available. Retry downloading later, " -"manually." +#: module/plugins/hoster/NetloadIn.py:182 +#, python-format +msgid "Netload: waiting between downloads %d s." msgstr "" -#: module/plugins/hoster/MegauploadCom.py:272 -msgid "Wrong password for download link." +#: module/plugins/hoster/NetloadIn.py:213 +#, python-format +msgid "Netload: waiting for captcha %d s." msgstr "" -#: module/plugins/hoster/UploadedTo.py:131 -msgid "API key invalid" +#: module/plugins/hoster/NetloadIn.py:251 +msgid "Downloaded File was empty" msgstr "" -#: module/plugins/hoster/UploadedTo.py:155 +#: module/plugins/hoster/MegaDebridEu.py:49 #, python-format -msgid "%s: Not enough traffic left" -msgstr "" - -#: module/plugins/hoster/ShareonlineBiz.py:106 -msgid "Parallel download issue" +msgid "Impossible to connect to %s" msgstr "" -#: module/plugins/hoster/ShareonlineBiz.py:121 -msgid "Invalid download ticket" +#: module/plugins/hoster/MegaDebridEu.py:89 +#, python-format +msgid "Impossible to debrid %s" msgstr "" -#: module/plugins/hoster/RehostTo.py:26 -msgid "Please enter your rehost.to account or deactivate this plugin" +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" msgstr "" -#: module/plugins/hoster/FileserveCom.py:87 -msgid "Not logged in." +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" msgstr "" -#: module/plugins/hoster/FileserveCom.py:112 -msgid "Parallel download error, now waiting 60s." +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" msgstr "" #: module/plugins/hoster/RapidshareCom.py:99 @@ -585,7 +599,7 @@ msgid "Rapidshare: Traffic Share (direct download)" msgstr "" #: module/plugins/hoster/RapidshareCom.py:126 -#: module/plugins/hoster/RapidshareCom.py:192 +#: module/plugins/hoster/RapidshareCom.py:193 msgid "Already downloading from this ip address, waiting 60 seconds" msgstr "" @@ -593,274 +607,293 @@ msgstr "" msgid "Invalid Auth Code, download will be restarted" msgstr "" -#: module/plugins/hoster/RapidshareCom.py:196 +#: module/plugins/hoster/RapidshareCom.py:198 msgid "RapidShareCom: No free slots" msgstr "" -#: module/plugins/hoster/RapidshareCom.py:199 +#: module/plugins/hoster/RapidshareCom.py:201 msgid "You need a premium account for this file" msgstr "" -#: module/plugins/hoster/RapidshareCom.py:201 +#: module/plugins/hoster/RapidshareCom.py:203 msgid "Filename reported invalid" msgstr "" -#: module/plugins/hoster/FilesMailRu.py:99 -msgid "There was HTML Code in the Downloaded File(" +#: module/plugins/hoster/FileserveCom.py:100 +msgid "Parallel download error, now waiting 60s." msgstr "" -#: module/plugins/hoster/NetloadIn.py:141 -#: module/plugins/hoster/NetloadIn.py:161 -msgid "File temporarily not available" +#: module/plugins/hoster/FileserveCom.py:216 +msgid "Not logged in." msgstr "" -#: module/plugins/hoster/NetloadIn.py:174 -#, python-format -msgid "Netload: waiting between downloads %d s." +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" msgstr "" -#: module/plugins/hoster/NetloadIn.py:203 -#, python-format -msgid "Netload: waiting for captcha %d s." +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" msgstr "" -#: module/plugins/hoster/NetloadIn.py:242 -msgid "Downloaded File was empty" +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" msgstr "" -#: module/plugins/hoster/RealdebridCom.py:37 -msgid "Please enter your Real-debrid account or deactivate this plugin" +#: module/plugins/Container.py:68 +msgid "File not exists." msgstr "" -#: module/plugins/container/LinkList.py:54 -msgid "LinkList could not be cleared." +#: module/plugins/hooks/UpdateManager.py:97 +msgid "Not able to connect server to get updates" msgstr "" -#: module/plugins/Plugin.py:381 -msgid "" -"Pil and tesseract not installed and no Client connected for captcha " -"decrypting" +#: module/plugins/hooks/UpdateManager.py:111 +msgid "No pyLoad version available" msgstr "" -#: module/plugins/Plugin.py:385 -msgid "No captcha result obtained in appropiate time by any of the plugins." +#: module/plugins/hooks/UpdateManager.py:118 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:119 +msgid "*** Get it here: https://github.com/pyload/pyload/releases ***" msgstr "" -#: module/plugins/Plugin.py:490 module/plugins/Plugin.py:520 +#: module/plugins/hooks/UpdateManager.py:170 #, python-format -msgid "Setting User and Group failed: %s" +msgid "New version of [%(type)s] %(name)s (v%(oldver)s -> v%(newver)s)" msgstr "" -#: module/plugins/Container.py:68 -msgid "File not exists." +#: module/plugins/hooks/UpdateManager.py:180 +#: module/plugins/hooks/UpdateManager.py:185 +#, python-format +msgid "Error when updating plugin %s" msgstr "" -#: module/plugins/accounts/MegauploadCom.py:41 -msgid "Activate direct Download in your MegaUpload Account" +#: module/plugins/hooks/UpdateManager.py:185 +msgid "Version mismatch" msgstr "" -#: module/plugins/accounts/FilesonicCom.py:49 -msgid "Invalid login retrieving user details" +#: module/plugins/hooks/UpdateManager.py:196 +#, python-format +msgid "Removed blacklisted plugin: [%(type)s] %(name)s" msgstr "" -#: module/plugins/accounts/BitshareCom.py:36 -msgid "Activate direct Download in your Bitshare Account" +#: module/plugins/hooks/UpdateManager.py:204 +msgid "Plugins updated and reloaded" msgstr "" -#: module/plugins/PluginManager.py:153 -#, python-format -msgid "%s has a invalid pattern." +#: module/plugins/hooks/UpdateManager.py:206 +msgid "*** Plugins have been updated, pyLoad will be restarted now ***" msgstr "" -#: module/plugins/PluginManager.py:272 -#, python-format -msgid "Error importing %(name)s: %(msg)s" +#: module/plugins/hooks/UpdateManager.py:211 +msgid "No plugin updates available" msgstr "" -#: module/plugins/AccountManager.py:88 -msgid "Account settings deleted, due to new config format." +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " msgstr "" -#: module/plugins/internal/MultiHoster.py:60 -msgid "No Hoster loaded" +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" msgstr "" -#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#: module/plugins/hooks/IRCInterface.py:96 #, python-format -msgid "Could not login with account %(user)s | %(msg)s" +msgid "Answer with 'c %s text on the captcha'" msgstr "" -#: module/plugins/Account.py:86 -msgid "Wrong Password" +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" msgstr "" -#: module/plugins/Account.py:240 +#: module/plugins/hooks/HotFolder.py:81 #, python-format -msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgid "Added %s from HotFolder" msgstr "" -#: module/plugins/Account.py:266 +#: module/plugins/hooks/ExtractArchive.py:94 #, python-format -msgid "Account %s has not enough traffic, checking again in 30min" +msgid "No %s installed" msgstr "" -#: module/plugins/Account.py:273 +#: module/plugins/hooks/ExtractArchive.py:96 +#: module/plugins/hooks/ExtractArchive.py:101 #, python-format -msgid "Account %s is expired, checking again in 1h" +msgid "Could not activate %s" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "finished" +#: module/plugins/hooks/ExtractArchive.py:106 +msgid "Activated" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "offline" +#: module/plugins/hooks/ExtractArchive.py:108 +msgid "No Extract plugins activated" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "online" +#: module/plugins/hooks/ExtractArchive.py:120 +#, python-format +msgid "Package %s queued for later extracting" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "queued" +#: module/plugins/hooks/ExtractArchive.py:143 +#, python-format +msgid "Check package %s" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "skipped" +#: module/plugins/hooks/ExtractArchive.py:184 +#, python-format +msgid "Extract to %s" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "waiting" +#: module/plugins/hooks/ExtractArchive.py:199 +msgid "No files found to extract" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "temp. offline" +#: module/plugins/hooks/ExtractArchive.py:206 +msgid "extracting" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "starting" +#: module/plugins/hooks/ExtractArchive.py:217 +msgid "Password protected" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "failed" +#: module/plugins/hooks/ExtractArchive.py:238 +msgid "Wrong password" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "aborted" +#: module/plugins/hooks/ExtractArchive.py:246 +#, python-format +msgid "Deleting %s files" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "decrypting" +#: module/plugins/hooks/ExtractArchive.py:253 +msgid "Extracting finished" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "custom" +#: module/plugins/hooks/ExtractArchive.py:259 +msgid "Archive Error" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "downloading" +#: module/plugins/hooks/ExtractArchive.py:261 +msgid "CRC Mismatch" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "processing" +#: module/plugins/hooks/ExtractArchive.py:265 +msgid "Unknown Error" msgstr "" -#: module/database/FileDatabase.py:47 -msgid "unknown" +#: module/plugins/hooks/ExtractArchive.py:317 +msgid "Setting User and Group failed" msgstr "" -#: module/database/DatabaseBackend.py:174 -msgid "Filedatabase was deleted due to incompatible version." +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" msgstr "" -#: module/database/DatabaseBackend.py:189 -msgid "Filedatabase could NOT be converted." +#: module/plugins/hooks/CaptchaTrader.py:70 +#: module/plugins/hooks/Captcha9kw.py:60 +#: module/plugins/hooks/ExpertDecoders.py:51 +#, python-format +msgid "%s credits left" msgstr "" -#: module/database/DatabaseBackend.py:198 -msgid "Database was converted from v2 to v3." +#: module/plugins/hooks/CaptchaTrader.py:118 +msgid "Could not send response." msgstr "" -#: module/database/DatabaseBackend.py:206 -msgid "Database was converted from v3 to v4." +#: module/plugins/hooks/CaptchaTrader.py:136 +msgid "Your CaptchaTrader Account has not enough credits" msgstr "" -#: module/database/DatabaseBackend.py:252 -msgid "Converting old Django DB" +#: module/plugins/hooks/LinkdecrypterCom.py:45 +msgid "Crypter list not found" msgstr "" -#: module/network/HTTPDownload.py:245 -#, python-format -msgid "Download chunks failed, fallback to single connection | %s" +#: module/plugins/hooks/LinkdecrypterCom.py:59 +msgid "Crypter list is empty" msgstr "" -#: module/PluginThread.py:183 +#: module/plugins/hooks/XMPPInterface.py:91 #, python-format -msgid "Download starts: %s" +msgid "Download finished: %(name)s @ %(plugin)s" msgstr "" -#: module/PluginThread.py:189 +#: module/plugins/hooks/Captcha9kw.py:94 #, python-format -msgid "Download finished: %s" +msgid "New CaptchaID from upload: %s : %s" msgstr "" -#: module/PluginThread.py:194 module/PluginThread.py:366 -#, python-format -msgid "Plugin %s is missing a function." +#: module/plugins/hooks/Captcha9kw.py:130 +msgid "Your Captcha 9kw.eu Account has not enough credits" msgstr "" -#: module/PluginThread.py:202 module/PluginThread.py:265 -#: module/PluginThread.py:383 +#: module/plugins/hooks/ExternalScripts.py:54 #, python-format -msgid "Download aborted: %s" +msgid "Installed scripts for %s: " msgstr "" -#: module/PluginThread.py:222 -#, python-format -msgid "Download restarted: %(name)s | %(msg)s" +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" msgstr "" -#: module/PluginThread.py:231 module/PluginThread.py:374 +#: module/plugins/hooks/ExternalScripts.py:80 #, python-format -msgid "Download is offline: %s" +msgid "Error in %(script)s: %(error)s" msgstr "" -#: module/PluginThread.py:234 -#, python-format -msgid "Download is temporary offline: %s" +#: module/plugins/hooks/ExpertDecoders.py:96 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" msgstr "" -#: module/PluginThread.py:237 module/PluginThread.py:304 +#: module/plugins/hooks/PremiumizeMe.py:50 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:70 #, python-format -msgid "Download failed: %(name)s | %(msg)s" +msgid "%d credits left" msgstr "" -#: module/PluginThread.py:254 +#: module/plugins/Plugin.py:389 msgid "" -"Couldn't connect to host or connection reset, waiting 1 minute and retry." +"Pil and tesseract not installed and no Client connected for captcha " +"decrypting" msgstr "" -#: module/PluginThread.py:290 -#, python-format -msgid "Download skipped: %(name)s due to %(plugin)s" +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." msgstr "" -#: module/PluginThread.py:362 +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 #, python-format -msgid "Decrypting starts: %s" +msgid "Setting User and Group failed: %s" msgstr "" -#: module/PluginThread.py:377 module/PluginThread.py:395 -#, python-format -msgid "Decrypting failed: %(name)s | %(msg)s" +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" msgstr "" -#: module/PluginThread.py:389 +#: module/Api.py:330 #, python-format -msgid "Retrying %s" +msgid "Added package %(name)s containing %(count)d links" msgstr "" -#: module/PluginThread.py:636 +#: module/Api.py:593 #, python-format -msgid "Info Fetching for %(name)s failed | %(err)s" +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "" +"No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or " +"rhino" msgstr "" diff --git a/locale/crowdin.yaml b/locale/crowdin.yaml new file mode 100644 index 000000000..96898d500 --- /dev/null +++ b/locale/crowdin.yaml @@ -0,0 +1,15 @@ +project_identifier: pyload +preserve_hierarchy: true +api_key: {key} +base_path: {tmp} + +files: + - + source: 'pyLoad/*.pot' + translation: 'pyLoad/%two_letters_code%/LC_MESSAGES/%file_name%.po' + - + source: 'pyLoad/cli.pot' + translation: 'pyLoad/%two_letters_code%/LC_MESSAGES/pyLoadCli.po' + - + source: 'pyLoad/core.pot' + translation: 'pyLoad/%two_letters_code%/LC_MESSAGES/pyLoad.po' diff --git a/locale/cs/LC_MESSAGES/django.mo b/locale/cs/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index 3d771c127..000000000 --- a/locale/cs/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/cs/LC_MESSAGES/django.po b/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 000000000..deaf35622 --- /dev/null +++ b/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Czech\n" +"Language: cs_CZ\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Nová captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "ProsÃm pÅeÄtÄte text captchy." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad restartován" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "vypnuto" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "ÃspÄch" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "zapnuto" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Opravdu chcete ukonÄit pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Restartovat odkaz" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Smazat odkaz" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "ProsÃm zadejte jméno balÃÄku." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "ProsÃm, kliknÄte na správnou pozici captchy." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Nastala chyba." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "SloÅŸka je prázdná" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Selhalo" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Ŝádné Captchy k pÅeÄtenÃ." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Hesla se neshodujÃ." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Nastavenà uloÅŸeno." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nová sloÅŸka" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Opravdu chcete restartovat pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "cekam %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Aktivnà StahovánÃ" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Domů" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "StahovánÃ" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Logy" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Konfigurace" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Jméno" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Stav" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Informace" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Velikost" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Postup" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "PÅihlásit se" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "UÅŸivatelské jméno" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Heslo" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "VaÅ¡e uÅŸivatelské jméno a heslo se neshodujà s údaji v databázi. ProsÃm zkuste to znovu." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Pro reset vaÅ¡ich pÅihlaÅ¡ovacÃch údajů nebo pÅidánà uÅŸivatele spusÅ¥te:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Smazat dokonÄené" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Restartovat nezdaÅené" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "SloÅŸka:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Heslo:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Upravit BalÃÄek" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "NÃÅŸe upravte vlastnosti balÃÄku." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Jméno balÃÄku." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "SloÅŸka" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Jméno podsloÅŸky pro toto stahovánÃ." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Seznam hesel pouÅŸitÜch pro unrar." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Odeslat" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Byli jste úspÄÅ¡nÄ odhlášeni." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Cesta" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absolutnÃ" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativnÃ" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "jméno" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "velikost" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "typ" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "naposledy upraveno" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "nadÅazenÜ adresáÅ" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "şádnÜ obsah" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Obecné" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Pluginy" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "ÃÄty" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Vyberte sekci z menu" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "DoplnÄk" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "PlatnÜ do" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "ZbÜvá traffic" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Äas" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Max SouÄasnÄ" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Smazat?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "platnÜ" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "neplatnÜ" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "ano" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "ne" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "PÅidat" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "PÅidat ÃÄet" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Pro pÅÃstup k prémiovÜm funkcÃm vloÅŸte vaÅ¡e pÅÃstupová data." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "VaÅ¡e uÅŸivatelské jméno." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Heslo pro tento úÄet." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Typ" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Vyberte filehosting vaÅ¡eho úÄtu." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "pÅedchozÃ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "dalÅ¡Ã" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Konec" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Novinky" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Podpora" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Systém" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad verze:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "SloÅŸka instalace:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "SloÅŸka nastavenÃ:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "SloÅŸka stahovánÃ:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Volné MÃsto:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Jazyk:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Port Vzdaleneho Rozhrani:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "NastavenÃ" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "SouborovÜ ManaÅŸer" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "PÅidat BalÃÄek" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "VloÅŸte vaÅ¡e odkazy nebo uploadnÄte kontejner." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Jméno nového balÃÄku." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Odkazy" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Sem vloÅŸte vaÅ¡e odkazy nebo jakÜkoli text a stisknÄte tlaÄÃtko filtrovat." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtrovat URL" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Heslo pro archiv RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Soubor" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Upload kontejneru." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "CÃl" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Ätenà captchy" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "VloÅŸte text captchy." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "ZavÅÃt" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Webové rozhranÃ" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad Aktualizace k dispozici!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Pluginy aktualizovány, restartuj pyLoad!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha Äeká" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Odhlásit" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrace" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Informace" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "PÅihlaÅ¡te se prosÃm!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Zastavit" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "ZruÅ¡it" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "StahovánÃ:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Rychlost:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "AktivnÃ:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Obnovit stránku" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "naÄÃtám" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Nahoru" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "UkonÄit pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Restartovat pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Pro pÅidánà uÅŸivatele nebo zmÄnu hesla pouÅŸijte:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "DůleÅŸité: Admin má vÅŸdy plná práva!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "ZmÄnit heslo" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "OprávnÄnÃ" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "zmÄnit" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Zadejte aktuálnà a poÅŸadované heslo." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "UÅŸivatel" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Aktuálnà heslo" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nové heslo" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Nové heslo." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nové heslo (znovu)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "ProsÃm zadej nové heslo znovu." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Pro zobrazeni teto stranky nemate opravneni." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Adresar pro stahovani nenalezen." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "neomezenÜ" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "neni k dispozici" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Pro setup spustte pyload.py -s." + diff --git a/locale/cs/LC_MESSAGES/pyLoad.mo b/locale/cs/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index a0c01d4e9..000000000 --- a/locale/cs/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/cs/LC_MESSAGES/pyLoad.po b/locale/cs/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..386dfb739 --- /dev/null +++ b/locale/cs/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Czech\n" +"Language: cs_CZ\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Prijat Quit signal" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad je jiz spusten pod pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Zmena skupiny selhala: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Zmena uzivatele selhala: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "slozka pro logy" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Spoustim" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Nastaven domovsky adresar: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto pro dekodovani kontejnerovych souboru" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "slozka pro docasne soubory" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "slozka pro stahovani" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL pro zabezpecene pripojeni" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Presunuji stara nastaveni uzivatele do DB." + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Prosim zkontrolujte sve prihlasovaci udaje pres ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "VÅ¡echny odkazy odstranÄny" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Cas stahovani: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Volne misto: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Aktivuji Ucty..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Aktivuji Pluginy..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad je spusten" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "restartuji pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad se ukonci" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Instalujte %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "nelze najit %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "nelze vytvorit %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "vypinani..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "chyba pri vypinani" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyLoad zastaven z terminalu" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "Databaze souboru byla smazana pro nekompatibilni verzi." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Databáze nemůşe bÜt pÅevedena" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Databaze byla konvertovana z v2 na v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Databaze byla konvertovana z v3 na v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Konvertuji starou databazi Django" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "hotovo" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "ve fronte" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "preskoceno" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "ceka" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "doc. nedostupne" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "spoustim" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "selhalo" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "zruseno" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "dekoduji" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "vlastni" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "stahuji" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "zpracovavam" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "neznamy" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Balicek dokoncen: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "Pouzivam SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Vzdalena chyba systemu: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Zahajuji %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Spousteni backendu %(name)s selhalo | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "cekam %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "Certifikaty SSL nenalezeny." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Omlouvame se, ale spousteni %s v ramci pyLoad jiz neni podporovano" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Je mozne pouzit server podporujici vlakna, ktery nabizi dobry vykon a ssl," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "a samozrejme je take mozne pouzit vas jiz existujici %s se serverem fastcgi pyLoadu" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "vzorove konfiguracni soubory jsou umisteny v adresari module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Nelze pouzit %(server)s, python-flup neni nainstalovan!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Chyba pri importu lightweight serveru: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "MusÃte si stáhnout a zkompilovat bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Zkopirujte soubor boern.so do adresare module/lib nebo pouzijte setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Samozrejme budete potrebovat znalost linuxu a kompilace software" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Server nyni pracuje s vlakny i pres zname obtize s vykonem na Windows" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Tento server nenabizi SSL, zvazte pouziti rezimu s vlakny" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Spoustim vestaveny Webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Spoustim SSL webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Spoustim webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Spoustim fastcgi server: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Startuji lightweight server (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Pro zobrazeni teto stranky nemate opravneni." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Adresar pro stahovani nenalezen." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "neomezenÜ" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "neni k dispozici" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Pro setup spustte pyload.py -s." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Stahovánà Äástà selhalo, pÅecházÃm na jediné pÅipojenà | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Zahajuji stahovani: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Stahovani dokonceno: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "V pluginu %s chybi funkce." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Stahovani zruseno: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Stahovani obnoveno: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Zdroj stahovani je offline: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Zdroj stahovani je docasne nedostupny: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Stahovani selhalo: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "K hostiteli se nelze pripojit, nebo bylo pripojeni resetovano, cekam 1 minutu do dalsiho pokusu." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Stahovani preskoceno: %(name)s v dusledku %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Zacina dekodovani: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Dekodovani selhalo: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Zkousim znovu %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Ziskavani informaci pro %(name)s selhalo | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Chyba pri provadeni zaveseni: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Aktivace %(name)s selhala" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Aktivovane pluginy: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Deaktivovat pluginy: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Reconnect selhal: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Skript pro reconnect nenalezen!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Spoustim reconnect" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Provadeni skriptu pro Reconnect selhalo!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Reconnectnuto, nova IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Nenà dostatek mÃsta na zaÅÃzenÃ" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "NezdaÅÃlo se pÅihlášenà k úÄtu %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Å patné heslo" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "Vas cas %s ma nespravny format, pouzijte 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "ÃÄet %s nemá nedostatek trafficu, dalšà kontrola za 30min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "ÃÄet %s vyprÅ¡el, dalšà kontrola za 1h" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "DosaÅŸen limit pro stahovánÃ" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s ma neplatny vzor." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Chyba pri importu %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "NenaÄten şádnÜ plugin Hoster" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Aktivovat pÅÃmé stahovánà na vaÅ¡em Bitshare accountu" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "LinkList nemohl byt vyprazdnen." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Pro novy format konfiguracniho souboru bylo nastaveni uctu smazano." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Je vyÅŸadována autorizace (username:password)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "ProsÃm vloÅŸte svůj %s úÄet nebo tento plugin deaktivujte" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "Ve staÅŸeném souboru (%s) byl nalezen HTML kód... Chyba pÅesmÄrovánÃ? Stahovánà bude restartováno." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Soubor nenà doÄasnÄ k dispozici" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: Äekánà mezi stahovánÃm %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: Äekám na captchu %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "StaÅŸenÜ soubor byl prázdnÜ" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "NeplatnÜ API klÃÄ" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: NezbÜvá dostateÄnÜ traffic" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "PÅekroÄen Traffic" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "RapidShare: Traffic Share (pÅÃmé staÅŸenÃ)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Z této ip adresy jiÅŸ stahovánà probÃhá, Äekám 60 sekund" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Å patnÜ autentizaÄnà kód, stahovánà bude restartováno" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: Ŝádné volné sloty" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Pro tento soubor potÅebujete prémiovÜ úÄet" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Ohlášeno neplatné jméno souboru" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Chyba soubÄÅŸného stahovánÃ, Äekám 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Nejste pÅihlášeni." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "DeÅ¡ifrovánà selhalo" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "URL neobsahuje klÃÄ souboru" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Kód chyby:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Soubor neexistuje." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Pluginy byly aktualizovány, prosÃm restartujte pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Pluginy aktualizovány a znovu naÄteny" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Ŝádné aktualizace rozÅ¡ÃÅenÃ" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Ŝádné aktualizace pro pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Je dostupná nové verze pyLoad (%s) ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** ZÃskejte ji zde: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Nelze se pÅipojit k update serveru" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nová verze %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Chyba pÅi aktualizaci %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "Nesprávná verze" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Stahovánà dokonÄeno: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "NovÜ poÅŸadavek na Captchu: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "OdpovÄzte \"c %s text z captchy\"" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "NejdÅÃve prosÃm pÅidejte váš premium.to úÄet a restartujte pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "PÅidán %s ze sledované sloÅŸky" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "%s nenà nainstalován" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Nelze aktivovat %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "AktivnÃ" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Nejsou aktivovány şádné rozbalovacà pluginy" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "BalÃÄek %s zaÅazen do fronty pro pozdÄjšà rozbalenÃ" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Kontrola balÃÄku %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Rozbalit do %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Nenalezeny şádné soubory k rozbalenÃ" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "rozbaluji" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "ChránÄno heslem" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Chybné heslo" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "MaÅŸu %s souborů" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Rozbalenà dokonÄeno" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Chyba archivu" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC nesouhlasÃ" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Neznámá chyba" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Nastavenà UÅŸivatele a Skupiny selhalo" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: Port 9666 se jiÅŸ pouÅŸÃvá" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s kreditů zbÜvá" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Nelze odeslat odpovÄÄ." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Na vaÅ¡em CaptchaTrader úÄtu nenà dostatek kreditu" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Seznam pluginů Crypter nenalezen" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Seznam pluginů Crypter je prázdnÜ" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Stahovánà dokonÄeno: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Nové CaptchaID z uploadu: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Na vaÅ¡em captcha úÄtu 9kw.eu nenà dostatek kreditu" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Nainstalované skripty pro %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Skript nenà spustitelnÜ:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Chyba v %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Na vaÅ¡m ExpertDecoders úÄtu nenà dostatek kreditu" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "NejdÅÃve prosÃm pÅidejte váš rehost.to úÄet a restartujte pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "NejdÅÃve prosÃm pÅidejte váš premiumize.me úÄet a restartujte pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "ZbÜvá %d kreditů" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil a tesseract nejsou nainstalovány a nenà pÅipojen şádnÜ klient pro rozpoznávánà Captchy" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Zadny plugin nedodal vysledek Captchy v prijatelnem case." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Nastavenà uÅŸivatele a skupiny se nezdaÅilo: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Neni pripojen zadny klient pro dekodovani Captchy" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Pridan balicek %(name)s obsahujici %(count)d odkazu" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Do balicku #%(package)d pridano %(count)d odkazu " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Nenalezen zadny js engine, prosim naistalujte Spidermonkey, ossp-js, pyv8 nebo rhino" + diff --git a/locale/cs/LC_MESSAGES/pyLoadCli.mo b/locale/cs/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 6f8b94b67..000000000 --- a/locale/cs/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/cs/LC_MESSAGES/pyLoadCli.po b/locale/cs/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..02483efb5 --- /dev/null +++ b/locale/cs/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Czech\n" +"Language: cs_CZ\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " PÅÃkazová Åádka" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s StahovánÃ:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Rychlost: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Velikost: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " DokonÄeno za: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "Äeká: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Stav:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "pozastaveno" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "probÃhá" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "celková rychlost" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Souborů ve frontÄ" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Celkem" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " PÅidat Odkazy" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Správa fronty" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " Správa SbÄraÄe" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " Pozastavit/Spustit server" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " UkonÄit server" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Konec" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "ProsÃm pouÅŸijte tuto syntaxi: add <Jmeno balicku> <odkaz> <odkaz2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Kontroluji %d odkazů:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Soubor neexistuje." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad byl ukonÄen" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "VypÃÅ¡e stav serveru" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "VypÃÅ¡e stahovánà ve frontÄ" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "VypÃÅ¡e stahovánà ve sbÄraÄi" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "PÅidá balÃÄek do fronty" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "PÅidá balÃÄek do sbÄraÄe" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Smazat soubory z fronty/sbÄraÄe" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Smazat balÃÄky z fronty/sbÄraÄe" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "PÅesun balÃÄku z fronty do sbÄraÄe nebo naopak" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Restart souborů" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Restart balÃÄků" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Zkontrolovat stav online - funguje s mÃstnÃm zásobnÃkem" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Zkontroluje online stav souboru ze zásobnÃku" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Pozastavit server" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "pokracovat ve stahovani" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Prepnout pozastaveni/beh" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "ukoncit server" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Seznam prikazu:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Nemohu zapsat nastavenà uÅŸivatele" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Pro pripojeni k tomuto jadru pyLoad je vyzadovano py-openssl." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adresa: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Uzivatelske jmeno: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Heslo: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Prihlasovaci udaje jsou chybne." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Nelze vytvorit pripojeni k %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "K pripojeni na toto pyLoad jadro potrebujete py-openssl." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Byly zadany prikazy, interaktivni mod je ignorovan." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "PÅidat BalÃÄek:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Zadej název nového balÃÄku" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "BalÃÄek: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Analyzuje odkazy které chcete pÅidat." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Pokud jste hotovi, napiÅ¡te %s" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "PÅidáno odkazů: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " zpÄt do hlavnÃho menu" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Správa balÃÄků:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr " Spravovat Odkazy:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Co chcete pÅesunout?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Co chcete smazat?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Co chcete restartovat?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Vyberte si, co chcete dÄlat, nebo zadejte ÄÃslo balÃÄku." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "smazat" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "pÅesunout" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "restartovat" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - pÅedchozÃ" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - dalÅ¡Ã" + diff --git a/locale/cs/LC_MESSAGES/pyLoadGui.mo b/locale/cs/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index c913703f1..000000000 --- a/locale/cs/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/cs/LC_MESSAGES/setup.mo b/locale/cs/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index 91ab321ec..000000000 --- a/locale/cs/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/cs/LC_MESSAGES/setup.po b/locale/cs/LC_MESSAGES/setup.po new file mode 100644 index 000000000..25c99bd7a --- /dev/null +++ b/locale/cs/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Czech\n" +"Language: cs_CZ\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "a" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Vitejte v konfiguracnim pruvodci programu pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Zkontroluje vas system a provede zakladni nastaveni pro spusteni programu pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "Hodnota v zavorkach [] je vzdy vychozi," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "v pripade, ze ji nechcete zmenit nebo si nejste jisti co vybrat, jen stisknete enter." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Nezapomente: Tohoto pruvodce muzete kdykoli sputit znovu pouzitim parametru --setup nebo -s pri startu pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Pokud mate s pruvodcem jakekoli problemy, stisknete CTRL-C" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "pro zruseni a zamezeni jeho automatickeho spusteni pri dalsim startu pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Az budete pripraveni na kontrolu systemu, stisknete enter." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Pro beh pyLoad je potreba pycurl a python verze 2.5, 2.6 nebo 2.7." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Prosim odstrante problem a znovu spustte pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "Setup bude nyni ukoncen." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Kontrola systemu ukoncena, stisknete enter pro zobrazeni zpravy o stavu." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Stav ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "dekodovani kontejneru" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "pripojeni ssl" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "automaticke rozpoznavani captchy" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Webové rozhranÃ" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "rozsirene Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "Dostupne funkce:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Chybejici funkce: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto nedostupne" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Toto potrebujede k dekodovani souboru kontejneru." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL nedostupne" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Je potreba k vytvoreni zabezpeceneho pripojeni k jadru nebo webovemu rozhrani." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Pokud budete pyLoad pouzivat pouze lokalne, ssl neni nutne." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "rozpoznavani Caprtchy nedostupne" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Je potreba jen pro nektere filehostingy pro neplaceny pristup." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "Gui nedostupne" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "Graficke Uzivatelske Rozhrani" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "nenalezeno zadne jadro JavaScriptu" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Toto budete potrebovat pro nektere Click'N'Load linky. Naistalujte Spidermonkey, ossp-js, pyv8 nebo rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Pokud chcete, muzete nyni zrusit instalaci a opravit nektere zavislosti." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Pokracovat v instalaci?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Chcete zmenit cestu k nastaveni? Stavajici je %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Pokud pouzivate pyLoad na serveru, nebo je domovsky oddil na vnitrni flash, muze byt dobre ji zmenit." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Zmenit cestu k nastaveni?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Chcete nastavit prihlasovaci udaje a zakladni volby?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Doporuceno pri prvnim spusteni." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Vytvorit zakladni nastaveni?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Prejete si nastavit ssl?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Nastavit ssl?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Prejete si nastavit webove rozhrani?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Nastavit webove rozhrani?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Nastaveni uspesne dokonceno." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Stiknete enter pro ukonceni a restartujte pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Kontrola Systemu ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Vase verze pythonu je prilis nova, prosim pouzijte verzi 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Vase verze pythonu je prilis stara, prosim pouzijte alespon Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Verze Pythonu: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Vase nainstalovana verze %s jinja2 je prilis stara." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Muzete bezpecne pokracovat, nicmene pokud bude webove rozhani nefunkcni," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "bude treba ji upgradovat nebo odistalovat, pyLoad jiz obsahuje knihovnu jinja2." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "jadro JS" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Zakladni nastaveni ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Nasledujici prihlasovaci udaje jsou platne pro CLI, GUI a webove rozhrani." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "UÅŸivatelské jméno" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Externà klientské aplikace (napÅ. GUI a CLI) vyÅŸadujà vzdálenÜ pÅÃstup pro fungovanà pÅes sÃÅ¥." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Pokud vÅ¡ak chcete pouÅŸÃvat pouze webové rozhranÃ, můşete jej zakázat a uÅ¡etÅit tak pamÄÅ¥." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Povolit vzdálenÜ pÅÃstup" + +#: module/setup.py:291 +msgid "Language" +msgstr "Jazyk" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Slozka pro stahovani" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Max soubeznych stahovani" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Pouzivat Reconnect?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Umisteni skriptu pro Reconnect" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Nastaveni Weboveho rozhrani ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Aktivovat webove rozhrani?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Adresa pro naslouchani, pokud pouzijete 127.0.0.1 nebo localhost, bude webove rozhrani pristupne pouze lokalne." + +#: module/setup.py:312 +msgid "Address" +msgstr "Adresa" + +#: module/setup.py:313 +msgid "Port" +msgstr "Port" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad nabizi mnoho vezri administrace, nize kratke vysvetleni." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Vychozi server, nejlepsi volba, pokud nevite, ktery vybrat." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Tento server nabizi SSl a je dobrou alternativou k vestavenemu." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Muze byt pouzit apachem, lighttpd, vyzaduje vsak nastaveni, ktere nemusi byt snadne." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Velmi svizna alternativa napsana v C, vyzaduje znalost linuxu a libev." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Stahnete jej zde: https://github.com/jonashaag/bjoern a zkompilujte" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "a zkopirujte bjoern.so do adresare module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Pozor: V nekterych zvlastnich pripadech neni vestaveny server funkcni. Pokud mate problemy s webovym rozhranim," + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "vratte se sem a zmente vestaveny server za server s vlakny." + +#: module/setup.py:329 +msgid "Server" +msgstr "Server" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Nastaveni SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Pro vytvoreni ssl certifikatu spustte tyto prikazy v konfiguracni slozce pyLoad:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Pokud jste skoncili a vse probehlo v poradku, muzete aktivovat SSL." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "Aktivovat SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Zvolte akci" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Vytvorit/Upravit uzivatele" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Seznam uzivatelu" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Odstranit uzivatele" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Konec" + +#: module/setup.py:376 +msgid "Users" +msgstr "Uzivatele" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Nastavuji novou cestu ke konfiguracnim souborum, stavajici konfigurace nebude prenesena!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Cesta ke konfiguracnim souborum" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Cesta ke konfiguracnim souborum byla zmenena, instalace se nyni ukonci, pro pokracovani ji prosim restartujte." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Stisknete enter pro ukonceni." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Nastaveni cesty ke konfiguracnim souborum selhalo: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: chybi" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Heslo: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Heslo je pÅÃliÅ¡ krátké. PouÅŸijte nejménÄ 4 znaky." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Heslo (znovu): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Hesla se neshodujÃ." + +#: module/setup.py:493 +msgid "yes" +msgstr "ano" + +#: module/setup.py:493 +msgid "true" +msgstr "pravda" + +#: module/setup.py:493 +msgid "t" +msgstr "p" + +#: module/setup.py:496 +msgid "no" +msgstr "ne" + +#: module/setup.py:496 +msgid "false" +msgstr "nepravda" + +#: module/setup.py:496 +msgid "f" +msgstr "n" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Neplatne zadani" + diff --git a/locale/da/LC_MESSAGES/django.po b/locale/da/LC_MESSAGES/django.po new file mode 100644 index 000000000..786082c8e --- /dev/null +++ b/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Danish\n" +"Language: da_DK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Ny Captcha anmodning" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "LÊs venligst teksten i captcha" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad genstartet" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Succes" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Er du virkelig sikker pÃ¥ du vil lukke pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Genstart Link" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Slet link" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Indtast venligst et pakkenavn" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Tryk venligst pÃ¥ den hÞjre captcha" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Fejl opstod" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Mappen er tom" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Ingen Captcha at lÊse" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Adgangskoden stemte ikke overens" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Indstillinger gemt." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Ny mappe" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Er du sikker pÃ¥ du vil genstarte pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Aktive hentninger" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Hjem" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Logfiler" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Konfiguration" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Fremskridt" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Dit brugernavn og adgangskode stemte ikke overens. PrÞv venligst igen." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "For at nulstille dine logind data eller tilfÞje en bruger kÞr:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Slet afsluttede" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Genstart mislykkedes" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Mappe:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Adgangskode:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Redigér pakke" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Redigér pakke detaljerne nedenfor." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Pakkens navn." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Navnet pÃ¥ disse nedhentnigers undermappe." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Liste over adgangskoder brugt til unrar." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Nulstil" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Du er logget ud med succes." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Sti" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absolut" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativ" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "navn" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "stÞrrelse" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "indtast" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "sidst Êndret" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "forrige mappe" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "intet indhold" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "VÊlg en sektion fra menuen" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Gyldig indtil" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Trafik tilbage" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Tid" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Maks paralelle" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Slet?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "ikke gyldig" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "ja" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "nej" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Indtast dine konto data for at benytte premium egenskaber." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Dit brugernavn." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Adgangskoden til denne konto." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "VÊlg udbyderen for din konto" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "forrige" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "nÊste" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Slut" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Nyheder" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Installations mappe:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Konfigurations mappe:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Download mappe:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Fri plads:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Sprog:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Webinterface port:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Fjerninterface port:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "FilManager" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "TilfÞj pakke:" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "IndsÊt dine links eller overfÞr en beholder." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Navnet pÃ¥ den nye pakke" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "IndsÊt dine links eller hvilkensomhelst tekst her og tryk filtrer knappen." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtrér urls" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Adgangskode for RAR-arkiv" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Fil" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "OverfÞr en beholder." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Captcha lÊser" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Captcha'en" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Tekst" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "IndsÊt teksten i captcha'en" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Webbrugerflade" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "TilgÊngelig pyLoad opdatering!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins blev opdateret, genstart venligst!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha venter" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Log af" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrér" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "info" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Log venligst ind!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Genstart:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Hastighed:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Aktiv:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Genhent side" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "indlÊser" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Tilbage til toppen" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Luk pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Genstart pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "For at tilfÞje bruger eller Êndre adgangskode brug:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Vigtigt: Admin brugere har altid alle rettigheder" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Skift adgangskode" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Rettigheder" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "skift" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Indtast din nuvÊrende og Þnskede adgangskode " + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Bruger" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "NuvÊrende adgangskode" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Ny adgangskode" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Den nye adgangskode." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Ny adgangskode (gentag)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Gentag venligst den nye adgangskode." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "ikke tilgÊngelig" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/da/LC_MESSAGES/pyLoad.po b/locale/da/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..84f0e21a3 --- /dev/null +++ b/locale/da/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Danish\n" +"Language: da_DK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Starter" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "mappe til midlertidige filer" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL til sikker forbindelse" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Fri plads: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Aktiverer konti..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "genstarter pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad afslutter" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Installér %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "lukker ned..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "fejl ved nedlukning" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "drÊbte pyLoad fra terminal" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "Starter" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "ikke tilgÊngelig" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/da/LC_MESSAGES/pyLoadCli.po b/locale/da/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..303155034 --- /dev/null +++ b/locale/da/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Danish\n" +"Language: da_DK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s Hentes:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "Hastighed:" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "StÞrrelse:" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "FÊrdig om:" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "ID:" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "Venter:" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "TilfÞj Links" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "Genoptag/Pause Server" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "Afslut Server" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "Afslut" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Brug venligst denne syntaks: add <Pakkens Navn> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad var afslutte" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Udskriver server status" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Flyt pakker fra kÞ til samler og opmvendt" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Genstart filer" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Genstart pakker" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Pause serveren" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "FortsÊt hentning" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Pause/Genoptag" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "Afslut server" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Kommando liste" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Kunne ikke skrive til bruger config filen" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Du mangler py-openssl for at tilslutte til denne pyLoad Kerne" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adresse:" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Port:" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Brugernavn:" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Kode:" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Login oplysninger er forkerte" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Can ikke etablere forbindelse til %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Du mangler py-openssl for at tilslutte til denne pyLoad Kerne" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Interaktiv tilstand ignoreres da du gik nogle kommandoer." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "IndsÊt de links du Þnsker at tilfÞje" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Skriv %s nÃ¥r du er fÊrdig." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Links tilfÞjet:" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "tilbage til hovedmenu" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "HÃ¥ndtér pakker:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "HÃ¥ndtér Links:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Hvad vil du flytte?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Hvad vil du slette?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Hvad vil du genstarte?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "slet" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "flyt" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "genstart" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "- forrige " + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "- nÊste" + diff --git a/locale/da/LC_MESSAGES/setup.po b/locale/da/LC_MESSAGES/setup.po new file mode 100644 index 000000000..8ae55af99 --- /dev/null +++ b/locale/da/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Danish\n" +"Language: da_DK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Webbrugerflade" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Kode:" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Adgangskoden stemte ikke overens" + +#: module/setup.py:493 +msgid "yes" +msgstr "ja" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "nej" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index 017f373dc..000000000 --- a/locale/de/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po new file mode 100644 index 000000000..cdcf10c1d --- /dev/null +++ b/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: German\n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Neue CAPTCHA-Anfrage" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Bitte lies den Text auf dem Captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad wurde neu gestartet" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "aus" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Erfolgreich" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "ein" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Bist du sicher, dass du pyLoad beenden möchtest?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Link neu starten" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Link löschen" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Bitte gib einen Paketnamen ein." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Bitte klicke auf die richtige Position im Captcha." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Ein Fehler ist aufgetreten." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Ordner ist leer" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Fehlgeschlagen" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Keine CAPTCHA's verfÃŒgbar." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Passwörter stimmen nicht ÃŒberein." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Einstellungen gespeichert" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Neuer Ordner" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Sicher, dass du pyLoad neustarten willst?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "Warte %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Aktiv" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Start" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "Warteschlange" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "Linksammler" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Downloads" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Log" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Einstellungen" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Name" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Status" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Informationen" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "GröÃe" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Fortschritt" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Anmeldung" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Benutzername" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Passwort" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Dein Benutzername und/oder Passwort sind falsch. Bitte versuche es noch einmal." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Um deine Login-Informationen zu resetten oder un einen Benutzer hinzuzufÃŒgen, starte:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Fertige löschen" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Fehlgeschlagene neustarten" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Ordner:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Passwort:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Paket bearbeiten" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Bearbeiten Sie hier die Paketdetails." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Name des Pakets." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Verzeichnis" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Name des Unterordners fÃŒr diese Downloads." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Liste der Passwörter, welche fÃŒr das Entpacken genutzt werden." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Ãbernehmen" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Abbrechen" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Du wurdest erfolgreich abgemeldet." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Pfad" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absolut" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativ" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "Name" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "GröÃe" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "Typ" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "zuletzt verÀndert" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "ÃŒbergeordnetes Verzeichnis" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "kein Inhalt" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Allgemein" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Zusatzprogramme" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Konten" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "WÀhle einen Abschnitt aus dem MenÃŒ." + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Erweiterung" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "Premium" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "GÃŒltig bis:" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Verbleibender Traffic:" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Zeit:" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Max Parallel" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Löschen?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "gÃŒltig" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "ungÃŒltig" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "ja" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "nein" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "HinzufÃŒgen" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Konto hinzufÃŒgen" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Gib deine Benutzerdaten ein, um die Premiumfunktionen zu nutzen." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Dein Benutzername." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Das Password fÃŒr diesen Account." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Typ" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "WÀhle den Hoster fÃŒr dein Benutzerkonto." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Starten" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "zurÃŒck" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "weiter" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Ende" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Neuigkeiten" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Support" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "System" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "Python:" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "Betriebssystem:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad Version:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Installationsordner:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Konfigurationsordner:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Downloadordner:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Freier Speicherplatz:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Sprache:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Webinterface Port:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Remoteinterface Port:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Konfiguration" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Dateimanager" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Paket hinzufÃŒgen" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Links einfÃŒgen oder Container hochladen." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Name des neuen Pakets." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Links" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "FÃŒge deine Links oder einen Text hier ein und drÃŒck den 'Filter' Knopf" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Links filtern" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Passwörter fÃŒr RAR-Dateien" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Datei" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Container hochladen." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Ziel" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Captchas lesen" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "Captcha" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Das Captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Text" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Gib den Text aus dem Captcha ein." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "SchlieÃen" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "WeboberflÀche" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad Update verfÃŒgbar!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins aktualisiert, bitte pyLoad neustarten!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captchas verfÃŒgbar" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Abmelden" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrieren" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Info" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Bitte anmelden!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Stoppen" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Abbrechen" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Download:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Erneut verbinden:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Geschwindigkeit:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Aktiv:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Aktualisieren" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "lade" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Nach oben" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "pyLoad beenden" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "pyLoad neustarten" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Um Benutzer hinzuzufÃŒgen oder Passwörter zu Àndern benutze:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Wichtig: Admin User haben immer alle Berechtigungen!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Passwort Àndern" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "Admin" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Berechtigungen" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "Àndern" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Gib dein momentanes und dein neues Passwort ein." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Benutzer" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Momentanes Passwort" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Neues Passwort" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Das neue Passwort." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Neues Passwort (wiederholen)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Bitte wiederhole das neue Passwort." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Sie haben nicht die Berechtigung diese Seite zu besuchen." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Downloadverzeichnis nicht gefunden." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "unbegrenzt" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "nicht verfÃŒgbar" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Starte pyload.py -s um auf dieses Setup zuzugreifen." + diff --git a/locale/de/LC_MESSAGES/pyLoad.mo b/locale/de/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index e1e29cebc..000000000 --- a/locale/de/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/de/LC_MESSAGES/pyLoad.po b/locale/de/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..1b402845a --- /dev/null +++ b/locale/de/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: German\n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Signal zum Beenden erhalten" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad ist bereits gestartet mit der pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Fehler beim Ãndern der Gruppe: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Fehler beim Ãndern des Benutzers: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "Ordner fÃŒr Logs" + +#: module/Core.py:340 +msgid "Starting" +msgstr "starte" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Benutze Home-Verzeichnis: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pyCrypto um Containerdateien zu öffnen" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "Ordner fÃŒr temporÀre Dateien" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "Downloadordner" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL fÃŒr eine sichere Verbindung" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Migriere alte Benutzereinstellungen in die Datenbank..." + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Bitte ÃŒberprÃŒfe deine Login-Informationen mit './pyload.py -u'" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Alle Links entfernt" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Downloadzeit: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Freier Speicher: %sGB" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Aktiviere Konten..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Aktiviere Plugins..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad ist gestartet und lÀuft" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "starte pyLoad neu" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad wird beendet" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Installiere %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "konnte %(desc)s nicht finden: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "konnte %(desc)s nicht erstellen: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "Beenden..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "Fehler beim Beenden" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyLoad vom Terminal beendet" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "Link Datenbank wurde aufgrund inkompatibler Version gelöscht." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Link Datenbank konnte nicht konvertiert werden." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Datenbank wurde von v2 nach v3 konvertiert." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Datenbank wurde von v3 nach v4 konvertiert." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Konvertiere alte Django DB" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "Fertig" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "Offline" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "Online" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "eingereiht" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "ÃŒbersprungen" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "wartend" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "kurzzeitig offline" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "starte" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "fehlgeschlagen" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "abgebrochen" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "entschlÃŒsseln" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "benutzerdefiniert" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "downloade" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "verarbeite" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "unbekannt" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paket fertiggestellt: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "Nutze SSL Thrift Backend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Fehler beim Fernzugriff: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Starte %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Konnte Backend %(name)s nicht laden | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "Warte %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL Zertifikat nicht gefunden." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Entschuldigung! Wir haben den Support fÃŒr das Starten von %s direkt in pyLoad eingestellt" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Du kannst den multithreaded-server benutzen, welcher eine gute Performance, SSL und" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "natÃŒrlich kannst du weiterhin deine existierende %s mit pyLoads fastcgi server benutzen" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "Beispiel-Konfigurationsdateien befinden sich in dem Verzeichnis 'module/webui/servers'" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Kann %(server)s nicht benutzen, weil python-flup nicht installiert ist!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Fehler beim Laden vom lightweight Server: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "Du musst 'bjoern' herunterladen und kompilieren, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Kopiere 'boern.so' in 'module/lib' oder benutze 'setup.py install'" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "NatÃŒrlich musst musst etwas Ahnung von Linux haben und wie man Software kompiliert" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Der 'threaded' Server wird wegen Performance Problemen unter Windows benutzt." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "SSL funktioniert mit diesem Server nicht, benutze bitte alternativ den 'threaded' Server" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Starte den eingebauten Webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Starte den threaded SSL Webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Starte den threaded Webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Starte fastcgi Webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Starte bjoern Webserver: %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Sie haben nicht die Berechtigung diese Seite zu besuchen." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Downloadverzeichnis nicht gefunden." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "unbegrenzt" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "nicht verfÃŒgbar" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Starte pyload.py -s um auf dieses Setup zuzugreifen." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Eine Download Verbindung ist fehlggeschlagen, Falle zurÃŒck auf eine Verbindung | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Starte Download: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Download fertiggestellt: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Dem Plugin %s fehlt eine Funktion." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Download abgebrochen: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Download erneut gestartet: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Download ist nicht verfÃŒgbar: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Download ist vorÃŒbergehend nicht verfÃŒgbar: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Download fehlgeschlagen: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Verbindungsaufbau zum Host fehlgeschlagen oder die Verbindung wurde zurÃŒckgesetzt. Erneuter Versuch in 1 Minute..." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Download %(name)s wegen %(plugin)s ÃŒbersprungen" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Decrypting startet: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Decrypting fehlgeschlagen: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Wiederhole %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Holen von Informationen fÃŒr %(name)s fehlgeschlagen | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Fehler beim ausfÃŒhren des Hook: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Konnte %(name)s nicht aktivieren" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Aktivierte Plugins: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Deaktivierte Plugins: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "erneute Verbindung fehlgeschlagen: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Skript fÃŒr erneute Verbindung nicht gefunden!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "versuche erneute Verbindung" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Fehler beim AusfÃŒhren des Skriptes fÃŒr die erneute Verbindung!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Verbindung erneut aufgebaut, IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Auf dem GerÀt ist nicht mehr genÃŒgend Speicherplatz vorhanden" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Fehler beim Anmelden mit Konto %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Falsches Passwort" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "Ihre Zeit %s hat ein falsches Format, nutzen Sie dieses: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "Konto %s hat nicht genÃŒgend Traffic, erneuter Versuch in 30 min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "Konto %s ist abgelaufen, erneuter Versuch in 1Std" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "Downloadlimit erreicht" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s hat ein ungÃŒltiges Muster." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Fehler beim Importieren von %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Kein Hoster geladen" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Aktiviere direkten Download in deinem Bitshare Account" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "links.txt konnte nicht geleert werden." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Account-Einstellungen aufgrund neuem Konfigurationsformat gelöscht." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Authorisierung erforderlich (Benutzername:Passwort)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Bitte gib deine %s Kontodaten ein oder deaktiviere dieses Plugin" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "Es gab HTML-Code in der heruntergeladen Datei (%s)... Umleitungsfehler? Der Download wird neu gestartet." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Datei zur Zeit nicht verfÃŒgbar" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: warte zwischen den Downloads %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: Warte auf Captcha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "Die heruntergeladene Datei ist leer" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "API SchlÃŒssel ungÃŒltig" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: Nicht genÃŒgend Traffic ÃŒbrig" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Traffic ÃŒberschritten" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Traffic Share (direkter Download)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Von dieser IP Adresse wird bereits heruntergeladen, warte 60 Sekunden" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "UngÃŒltiger Authorization-Code, Download wird neugestartet" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: Keine freien Slots" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Du benötigst ein Premium-Konto fÃŒr diese Datei" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Dateiname als ungÃŒltig gemeldet" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Parallel-Download Fehler, warte 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Nicht eingeloggt." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "EntschlÃŒsselung fehlgeschlagen" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "FÃŒr die Datei wurde kein SchlÃŒssel in der URL ÃŒbertragen" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Fehler Code:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Datei existiert nicht." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Plugins wurden aktualisiert, bitte starte pyLoad neu ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Plugins aktualisiert und neu geladen" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Keine Plugin-Updates verfÃŒgbar" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Keine Updates fÃŒr pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Neue pyLoad Version %s verfÃŒgbar ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Download hier: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Konnte keine Verbindung zum Server herstellen, um auf Updates zu prÃŒfen" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Neue Version von %(type)s | %(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Fehler beim Aktualisieren von %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "Versionskonflikt" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Download fertig: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Neue Captcha Anfrage: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Beantworte Captcha mit \"c %s Text\"" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "Bitte fÃŒge erst dein premium.to Konto hinzu und starte pyLoad neu" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "%s aus HotFolder hinzugefÃŒgt" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "Kein %s installiert" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Konnte %s nicht aktivieren" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Aktiviert" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Keine Entpacken-Plugins aktiviert" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Paket %s eingereiht fÃŒr spÀteres entpacken" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "ÃberprÃŒfe Paket %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Entpacke nach %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Keine Dateien zum entpacken gefunden" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "entpacke" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "PasswortgeschÃŒtzt" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Falsches Passwort" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Lösche %s Dateien" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Entpacken abgeschlossen" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Archiv-Fehler" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC Fehler" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Unbekannter Fehler" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Setzen von Benutzer und Gruppe fehlgeschlagen" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: Port 9666 wird bereits verwendet" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s Credits verbleibend" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Konnte keine Antwort senden." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Dein CaptchaTrader Konto hat nicht genÃŒgend Credits" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Liste von Cryptern nicht gefunden" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Liste von Cryptern ist leer" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Download abgeschlossen: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Neue CaptchaID von Upload: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Dein Captcha 9kw.eu Account hat nicht genÃŒgend Credits" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Installierte Skripte fÃŒr %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Script nicht ausfÃŒhrbar:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Fehler in %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Dein ExpertDecoders Account hat nicht genÃŒgend Credits" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Bitte fÃŒgen Sie zuerst Ihr rehost.to Konto hinzu und starten Sie pyLoad danach neu" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "Bitte fÃŒge erst ein gÃŒltiges premiumize.me Konto hinzu und starte pyLoad neu." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d Credits verbleibend" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil und Tesseract sind nicht installiert und kein Client ist verbunden fÃŒr Captcha-Entzifferung" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Es konnte in angemessener zeit kein Captcha-Ergebnis durch dies Plugins ermittelt werden." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Benutzer und Gruppe setzen fehlgeschlagen: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Kein Client verbunden zum eingeben des Captchas" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Paket %(name)s mit %(count)d Links hinzugefÃŒgt" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "%(count)d Links wurden zum Paket #%(package)d hinzugefÃŒgt " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Keine JS Engine erkannt. Bitte installiere entweder Spidermonkey, ossp-js, pyv8 oder rhino" + diff --git a/locale/de/LC_MESSAGES/pyLoadCli.mo b/locale/de/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index e46503121..000000000 --- a/locale/de/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/de/LC_MESSAGES/pyLoadCli.po b/locale/de/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..86b59213c --- /dev/null +++ b/locale/de/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: German\n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Kommandozeile" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s Downloads:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Geschwindigkeit: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " GröÃe: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Fertig in: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "wartend: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Status:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "pausiert" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "lÀuft" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "Gesamtgeschwindigkeit" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Dateien in Warteschlange" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Gesamt" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "MenÃŒ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Links hinzufÃŒgen" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Warteschlange verwalten" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " Linksammler anpassen" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " Server fortsetzen/pausieren" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Server beenden" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Beenden" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Bitte benutze folgende Syntax: add <Package name> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "ÃberprÃŒfe %d Links:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Datei existiert nicht." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad wurde beendet" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Zeigt den Server-Status" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Zeigt die Warteschlange" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Zeigt den Linksammler" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "FÃŒgt Paket der Warteschlange hinzu" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "FÃŒgt Paket zum Linksammler hinzu" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Löscht Dateien aus der Warteschlange/Linksammler" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Löscht Pakete aus der Warteschlange/Linksammler" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Verschiebt Pakete aus der Warteschlange in den Linksammler oder umgekehrt" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Dateien neustarten" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Pakete neustarten" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "ÃberprÃŒfe Onlinestatus, funktioniert mit lokalen Containern" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Onlinestatus eines Containers prÃŒfen" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "pausiert den Server" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "Downloads fortsetzen" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Pause/Fortsetzen" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "Server beenden" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Liste aller Befehle:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Konnte Benutzer-Konfigurationsdatei nicht schreiben" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Du benötigst py-openssl um dich zu diesem pyLoad Server verbinden zu können." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adresse: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Port: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Benutzername: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Passwort: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Logindaten sind falsch." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Konnte keine Verbindung zu %(addr)s:%(port)s aufbauen." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Du benötigst py-openssl um dich zu diesem pyLoad Server verbinden zu können." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Befehle im interaktiven Modus werden ignoriert, wenn zusÀtzliche Befehle ÃŒbergeben wurden." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Paket hinzufÃŒgen:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Gib einen Namen fÃŒr das neue Paket ein" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Paket: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Kopiere die Links, die du hinzufÃŒgen willst." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "DrÃŒcke %s wenn du fertig bist." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "HinzugefÃŒgte Links: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " ZurÃŒck zum MenÃŒ" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Pakete verwalten:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Links verwalten:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Was möchtest du verschieben?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Was möchtest du löschen?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Was möchtest du neustarten?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "WÀhle, was du machen möchtest oder gib eine Paketnummer an." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "löschen" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "verschieben" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "neustarten" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - vorige Seite" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - nÀchste Seite" + diff --git a/locale/de/LC_MESSAGES/pyLoadGui.mo b/locale/de/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 8ead8383c..000000000 --- a/locale/de/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/de/LC_MESSAGES/setup.mo b/locale/de/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index 80ca3553e..000000000 --- a/locale/de/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/de/LC_MESSAGES/setup.po b/locale/de/LC_MESSAGES/setup.po new file mode 100644 index 000000000..ac026d48c --- /dev/null +++ b/locale/de/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: German\n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "j" + +#: module/setup.py:53 +msgid "n" +msgstr "n" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Willkommen im pyLoad Konfigurations Assistenten." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Er wird dein System prÃŒfen und einige Grundeinstellungen vornehmen um pyLoad ausfÃŒhren zu können," + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "Der Wert in Klammern [] ist immer der Standardwert," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "Falls du sie nicht Àndern möchtest oder unsicher bist, drÃŒcke einfach Enter." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Beachte: Du kannst diesen Assistenten jederzeit wieder mit dem --setup oder -s Parameter starten." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Falls du beenden willst, drÃŒcke STRG-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "um abzubrechen und ihn nicht mehr automatisch zu starten." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Wenn du fÃŒr die SystemÃŒberprÃŒfung bereit bist, drÃŒcke Enter." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Du brauchst pycurl, sqlite und python 2.5, 2.6 oder 2.7 um pyLoad zu starten." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Bitte korrigiere das und starte pyLoad neu." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "Das Setup wird sich nun beenden." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "System-Check beendet, drÃŒcke Enter um deinen Status Bericht zu sehen." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Status ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "Container decrypting" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "SSL Verbindung" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "Automatisches Captcha einlesen" + +#: module/setup.py:104 +msgid "GUI" +msgstr "GUI" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "WeboberflÀche" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "erweitertes Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "VerfÃŒgbare Funktionen:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Fehlende Funktionen: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "kein py-crypto verfÃŒgbar" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Du brauchst es, um Container Dateien zu öffnen." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "Kein SSL verfÃŒgbar" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Wird gebraucht falls du eine SSL Verbindung zu Core oder Webinterface einstellen willst." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Falls du nur lokal zugreifen willst, ist SSL ÃŒberflÃŒssig." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "keine Captcha Erkennung verfÃŒgbar" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Wird fÃŒr einige Hoster als Freeuser benötigt." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "GUI nicht verfÃŒgbar" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "Die Grafische Benutzer OberflÀche." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "keine JavaScript Engine gefunden" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Du benötigst das fÃŒr einige Click'n'Load links. Installiere Spidermonkey, ossp-js, pyv8 oder rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Du kannst das Setup nun abbrechen und AbhÀngigkeiten fixen, falls du willst." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Mit Setup fortfahren?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Möchtest du den Pfad zu den Konfigurationsdateien Àndern? Jetziger ist %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Falls du pyLoad auf einem Server benutzt, oder die home Partition auf einem internen Flashspeicher liegt, wÀr es eine gute Idee ihn zu Àndern." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Konfigurationspfad Àndern?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Wollen Sie die Anmeldedaten und Grundeinstellungen festlegen?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Wird fÃŒr den ersten Start empfohlen." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Grundeinstellungen vornehmen?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Willst du SSL konfigurieren?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "SSL konfigurieren?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Willst du das Webinterface konfigurieren?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Webinterface konfigurieren?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Setup erfolgreich beendet." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "DrÃŒcke Enter zum beenden und starte pyLoad neu" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## System Check ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Deine python version ist zu neu, benutze python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Deine Python Version ist zu alt, benutze mindestens 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Python Version: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Ihre installierte Version %s von jinja2 scheint veraltet zu sein." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Sie können problemlos fortfahren, sollte jedoch das Webinterface nicht funktionieren," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "sollten Sie es upgrade oder deinstallieren, pyload bringt eine ausreichende jinja2 Bibliothek mit." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "JS engine" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Grundeinstellungen ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Die folgenden Anmeldedaten sind fÃŒr CLI, GUI und Webinterface gÃŒltig." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Benutzername" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Externe Clients (GUI, CLI und andere) benötigen Fernzugriff, um via Netzwerk zugreifen zu können." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Solltest Du jedoch nur das Webinterface nutzen, kannst Du Ihn deaktivieren, um den Speicherverbrauch zu verringern." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Aktiviere Fernzugriff" + +#: module/setup.py:291 +msgid "Language" +msgstr "Sprache" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Download Ordner" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Maximale parallele Downloads" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Benutze Reconnect?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Reconnect Script Pfad" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Webinterface Setup ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Aktiviere Webinterface?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Adresse des Webservers. Falls du 127.0.0.1 oder localhost eintrÀgst wird das Webinterface nur lokal erreichbar sein." + +#: module/setup.py:312 +msgid "Address" +msgstr "Adresse" + +#: module/setup.py:313 +msgid "Port" +msgstr "Port" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad verfÃŒgt ÃŒber verschiedene Webserver, eine kurze ErklÀrung folgt." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Standardserver, beste Wahl wenn du nicht weiÃt welchen du wÀhlen sollst." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Dieser Server unterstÃŒtzt SSL und ist eine gute Alternative zu builtin." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Kann von apache, lighttpd benutzt werden. Muss konfiguriert werden, welches aber nicht sehr einfach ist." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Sehr schnelle Alternative geschrieben in C, benötigt libev und Linux-Kenntnisse." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Downloaden von: https://github.com/jonashaag/bjoern, danach kompilieren." + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "und kopiere die bjoern.so nach module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Achtung: In manchen FÀllen funktioniert der builtin Server nicht, wenn du Probleme mit dem Webinterface bemerkst." + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "komme zurÃŒck und Àndere den builtin server zu threaded hier" + +#: module/setup.py:329 +msgid "Server" +msgstr "Server" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Einstellungen fÃŒr SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "FÃŒhren Sie die folgenden Kommandos im pyLoad Konfigurationsordner aus, um ein SSL-Zertifikate zu erstellen:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Falls du fertig bist und alles erfolgreich war, kannst du nun SSL aktivieren." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "SSL aktivieren?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Aktion wÀhlen" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Erstelle/Bearbeite Nutzer" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Liste Nutzer auf" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Entferne Nutzer" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Verlassen" + +#: module/setup.py:376 +msgid "Users" +msgstr "Benutzer" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Setze neuen Config Pfad, momentane Konfiguration wird nicht ÃŒbernommen!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Config Pfad" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Config Pfad geÀndert, Setup wird nun beenden, bitte starte neu um weiterzumachen." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "DrÃŒcke Enter zum Beenden." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Fehler beim Setzen des Pfades fÃŒr die Konfiguration: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "%s: OK" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: fehlt" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Passwort: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Passwort zu kurz. Benutze mindestens 4 Zeichen." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Passwort (bestÀtigen): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Passwörter stimmen nicht ÃŒberein." + +#: module/setup.py:493 +msgid "yes" +msgstr "ja" + +#: module/setup.py:493 +msgid "true" +msgstr "ja" + +#: module/setup.py:493 +msgid "t" +msgstr "j" + +#: module/setup.py:496 +msgid "no" +msgstr "nein" + +#: module/setup.py:496 +msgid "false" +msgstr "nein" + +#: module/setup.py:496 +msgid "f" +msgstr "n" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "UngÃŒltige Eingabe" + diff --git a/locale/django.pot b/locale/django.pot index 81c9c7b6b..39b39aded 100644 --- a/locale/django.pot +++ b/locale/django.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: pyLoad 0.4.9\n" +"Project-Id-Version: pyLoad 0.4.10\n" "Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" -"POT-Creation-Date: 2011-12-07 19:21+0100\n" +"POT-Creation-Date: 2014-07-13 20:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,670 +17,673 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: module/web/translations.js:1 module/web/templates/default/base.html:123 -#: module/web/templates/default/base.html:124 -#: module/web/templates/default/settings_item.html:14 -msgid "on" +#: module/webui/translations.js:1 +msgid "New Captcha Request" msgstr "" -#: module/web/translations.js:2 module/web/templates/default/captcha.html:7 +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 msgid "Please read the text on the captcha." msgstr "" -#: module/web/translations.js:3 -msgid "Settings saved." +#: module/webui/translations.js:3 +msgid "pyLoad restarted" msgstr "" -#: module/web/translations.js:4 module/web/templates/default/base.html:123 -#: module/web/templates/default/base.html:124 -#: module/web/templates/default/settings_item.html:16 +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 msgid "off" msgstr "" -#: module/web/translations.js:5 +#: module/webui/translations.js:5 msgid "Success" msgstr "" -#: module/web/translations.js:6 -msgid "Passwords did not match." +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" msgstr "" -#: module/web/translations.js:7 -msgid "Delete Link" +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" msgstr "" -#: module/web/translations.js:8 -msgid "pyLoad restarted" +#: module/webui/translations.js:8 +msgid "Restart Link" msgstr "" -#: module/web/translations.js:9 -msgid "You are really sure you want to quit pyLoad?" +#: module/webui/translations.js:9 +msgid "Delete Link" msgstr "" -#: module/web/translations.js:10 +#: module/webui/translations.js:10 msgid "Please Enter a packagename." msgstr "" -#: module/web/translations.js:11 +#: module/webui/translations.js:11 msgid "Please click on the right captcha position." msgstr "" -#: module/web/translations.js:12 +#: module/webui/translations.js:12 msgid "Error occured." msgstr "" -#: module/web/translations.js:13 -msgid "New Captcha Request" +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" msgstr "" -#: module/web/translations.js:14 +#: module/webui/translations.js:14 msgid "Failed" msgstr "" -#: module/web/translations.js:15 +#: module/webui/translations.js:15 msgid "No Captchas to read." msgstr "" -#: module/web/translations.js:16 -#: module/web/templates/default/filemanager.html:65 -#: module/web/templates/default/folder.html:14 -msgid "Folder is empty" +#: module/webui/translations.js:16 +msgid "Passwords did not match." msgstr "" -#: module/web/translations.js:17 -msgid "Restart Link" +#: module/webui/translations.js:17 +msgid "Settings saved." msgstr "" -#: module/web/translations.js:18 +#: module/webui/translations.js:18 msgid "New folder" msgstr "" -#: module/web/translations.js:19 +#: module/webui/translations.js:19 msgid "Are you sure you want to restart pyLoad?" msgstr "" -#: module/web/pyload_app.py:125 -msgid "You dont have permission to access this page." -msgstr "" - -#: module/web/pyload_app.py:193 -msgid "Download directory not found." -msgstr "" - -#: module/web/pyload_app.py:260 module/web/pyload_app.py:267 -msgid "unlimited" -msgstr "" - -#: module/web/pyload_app.py:262 module/web/pyload_app.py:269 -msgid "not available" -msgstr "" - -#: module/web/pyload_app.py:509 -msgid "Run pyLoadCore.py -s to access the setup." -msgstr "" - -#: module/web/json_app.py:60 +#: module/webui/app/json.py:57 #, python-format msgid "waiting %s" msgstr "" -#: module/web/templates/default/info.html:14 -#: module/web/templates/default/info.html:15 -#: module/web/templates/default/home.html:239 -msgid "Information" +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" msgstr "" -#: module/web/templates/default/info.html:18 -msgid "News" +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" msgstr "" -#: module/web/templates/default/info.html:21 -msgid "Support" +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" msgstr "" -#: module/web/templates/default/info.html:37 -msgid "System" +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" msgstr "" -#: module/web/templates/default/info.html:40 -msgid "Python:" +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" msgstr "" -#: module/web/templates/default/info.html:44 -msgid "OS:" +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" msgstr "" -#: module/web/templates/default/info.html:48 -msgid "pyLoad version:" +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" msgstr "" -#: module/web/templates/default/info.html:52 -msgid "Installation Folder:" +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" msgstr "" -#: module/web/templates/default/info.html:56 -msgid "Config Folder:" +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" msgstr "" -#: module/web/templates/default/info.html:60 -msgid "Download Folder:" +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" msgstr "" -#: module/web/templates/default/info.html:64 -msgid "Free Space:" +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" msgstr "" -#: module/web/templates/default/info.html:68 -msgid "Language:" +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" msgstr "" -#: module/web/templates/default/info.html:72 -msgid "Webinterface Port:" +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" msgstr "" -#: module/web/templates/default/info.html:76 -msgid "Remote Interface Port:" +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" msgstr "" -#: module/web/templates/default/downloads.html:6 -#: module/web/templates/default/base.html:93 -#: module/web/templates/default/home.html:220 -msgid "Downloads" +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" msgstr "" -#: module/web/templates/default/filemanager.html:19 -msgid "FileManager" +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." msgstr "" -#: module/web/templates/default/admin.html:8 -#: module/web/templates/default/admin.html:9 -#: module/web/templates/default/base.html:59 -msgid "Administrate" +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" msgstr "" -#: module/web/templates/default/admin.html:13 -msgid "Quit pyLoad" +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" msgstr "" -#: module/web/templates/default/admin.html:14 -msgid "Restart pyLoad" +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" msgstr "" -#: module/web/templates/default/admin.html:18 -msgid "To add user or change passwords use:" +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" msgstr "" -#: module/web/templates/default/admin.html:19 -msgid "Important: Admin user have always all permissions!" +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" msgstr "" -#: module/web/templates/default/admin.html:25 -#: module/web/templates/default/settings.html:91 -#: module/web/templates/default/queue.html:82 -#: module/web/templates/default/window.html:7 -#: module/web/templates/default/home.html:237 -msgid "Name" +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" msgstr "" -#: module/web/templates/default/admin.html:28 -#: module/web/templates/default/admin.html:67 -msgid "Change Password" +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." msgstr "" -#: module/web/templates/default/admin.html:31 -msgid "Admin" +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." msgstr "" -#: module/web/templates/default/admin.html:34 -msgid "Permissions" +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" msgstr "" -#: module/web/templates/default/admin.html:41 -msgid "change" +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." msgstr "" -#: module/web/templates/default/admin.html:61 -#: module/web/templates/default/admin.html:91 -#: module/web/templates/default/settings.html:167 -#: module/web/templates/default/queue.html:97 -#: module/web/templates/default/captcha.html:33 +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 msgid "Submit" msgstr "" -#: module/web/templates/default/admin.html:69 -msgid "Enter your current and desired Password." +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" msgstr "" -#: module/web/templates/default/admin.html:70 -msgid "User" +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." msgstr "" -#: module/web/templates/default/admin.html:71 -#: module/web/templates/default/settings.html:179 -msgid "Your username." +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" msgstr "" -#: module/web/templates/default/admin.html:75 -msgid "Current password" +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" msgstr "" -#: module/web/templates/default/admin.html:76 -#: module/web/templates/default/settings.html:184 -msgid "The password for this account." +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" msgstr "" -#: module/web/templates/default/admin.html:80 -msgid "New password" +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" msgstr "" -#: module/web/templates/default/admin.html:81 -msgid "The new password." +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" msgstr "" -#: module/web/templates/default/admin.html:85 -msgid "New password (repeat)" +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" msgstr "" -#: module/web/templates/default/admin.html:86 -msgid "Please repeat the new password." +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" msgstr "" -#: module/web/templates/default/admin.html:92 -#: module/web/templates/default/settings.html:198 -#: module/web/templates/default/queue.html:98 -#: module/web/templates/default/window.html:41 -msgid "Reset" +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" msgstr "" -#: module/web/templates/default/settings.html:3 -#: module/web/templates/default/settings.html:4 -#: module/web/templates/default/base.html:102 -#: module/web/templates/default/home.html:229 -msgid "Config" +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" msgstr "" -#: module/web/templates/default/settings.html:16 +#: module/webui/themes/default/tml/settings.html:16 msgid "General" msgstr "" -#: module/web/templates/default/settings.html:17 +#: module/webui/themes/default/tml/settings.html:17 msgid "Plugins" msgstr "" -#: module/web/templates/default/settings.html:18 +#: module/webui/themes/default/tml/settings.html:18 msgid "Accounts" msgstr "" -#: module/web/templates/default/settings.html:45 -#: module/web/templates/default/settings.html:74 +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 msgid "Choose a section from the menu" msgstr "" -#: module/web/templates/default/settings.html:90 +#: module/webui/themes/default/tml/settings.html:90 msgid "Plugin" msgstr "" -#: module/web/templates/default/settings.html:92 -#: module/web/templates/default/settings.html:183 -#: module/web/templates/default/login.html:19 -#: module/web/templates/default/queue.html:92 -#: module/web/templates/default/window.html:21 -msgid "Password" -msgstr "" - -#: module/web/templates/default/settings.html:93 -#: module/web/templates/default/home.html:238 -msgid "Status" -msgstr "" - -#: module/web/templates/default/settings.html:94 +#: module/webui/themes/default/tml/settings.html:94 msgid "Premium" msgstr "" -#: module/web/templates/default/settings.html:95 +#: module/webui/themes/default/tml/settings.html:95 msgid "Valid until" msgstr "" -#: module/web/templates/default/settings.html:96 +#: module/webui/themes/default/tml/settings.html:96 msgid "Traffic left" msgstr "" -#: module/web/templates/default/settings.html:97 +#: module/webui/themes/default/tml/settings.html:97 msgid "Time" msgstr "" -#: module/web/templates/default/settings.html:98 +#: module/webui/themes/default/tml/settings.html:98 msgid "Max Parallel" msgstr "" -#: module/web/templates/default/settings.html:99 +#: module/webui/themes/default/tml/settings.html:99 msgid "Delete?" msgstr "" -#: module/web/templates/default/settings.html:121 +#: module/webui/themes/default/tml/settings.html:121 msgid "valid" msgstr "" -#: module/web/templates/default/settings.html:124 +#: module/webui/themes/default/tml/settings.html:124 msgid "not valid" msgstr "" -#: module/web/templates/default/settings.html:131 +#: module/webui/themes/default/tml/settings.html:131 msgid "yes" msgstr "" -#: module/web/templates/default/settings.html:134 +#: module/webui/themes/default/tml/settings.html:134 msgid "no" msgstr "" -#: module/web/templates/default/settings.html:168 -#: module/web/templates/default/settings.html:197 -#: module/web/templates/default/base.html:117 +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 msgid "Add" msgstr "" -#: module/web/templates/default/settings.html:176 +#: module/webui/themes/default/tml/settings.html:176 msgid "Add Account" msgstr "" -#: module/web/templates/default/settings.html:177 +#: module/webui/themes/default/tml/settings.html:177 msgid "Enter your account data to use premium features." msgstr "" -#: module/web/templates/default/settings.html:178 -#: module/web/templates/default/login.html:3 -msgid "Login" +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." msgstr "" -#: module/web/templates/default/settings.html:188 +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 msgid "Type" msgstr "" -#: module/web/templates/default/settings.html:189 +#: module/webui/themes/default/tml/settings.html:189 msgid "Choose the hoster for your account." msgstr "" -#: module/web/templates/default/pathchooser.html:39 -#: module/web/templates/default/pathchooser.html:41 -msgid "Path" +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" msgstr "" -#: module/web/templates/default/pathchooser.html:39 -#: module/web/templates/default/pathchooser.html:41 -msgid "absolute" +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" msgstr "" -#: module/web/templates/default/pathchooser.html:39 -#: module/web/templates/default/pathchooser.html:41 -msgid "relative" +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" msgstr "" -#: module/web/templates/default/pathchooser.html:46 -msgid "name" +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" msgstr "" -#: module/web/templates/default/pathchooser.html:47 -msgid "size" +#: module/webui/themes/default/tml/info.html:18 +msgid "News" msgstr "" -#: module/web/templates/default/pathchooser.html:48 -msgid "type" +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" msgstr "" -#: module/web/templates/default/pathchooser.html:49 -msgid "last modified" +#: module/webui/themes/default/tml/info.html:37 +msgid "System" msgstr "" -#: module/web/templates/default/pathchooser.html:54 -msgid "parent directory" +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" msgstr "" -#: module/web/templates/default/pathchooser.html:70 -msgid "no content" +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" msgstr "" -#: module/web/templates/default/setup.html:3 -#: module/web/templates/default/setup.html:4 -msgid "Setup" +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" msgstr "" -#: module/web/templates/default/login.html:14 -msgid "Username" +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" msgstr "" -#: module/web/templates/default/login.html:29 -msgid "Your username and password didn't match. Please try again." +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" msgstr "" -#: module/web/templates/default/login.html:30 -msgid "To reset your login data or add an user run:" +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" msgstr "" -#: module/web/templates/default/base.html:20 -#: module/web/templates/default/base.html:139 -msgid "Webinterface" +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" msgstr "" -#: module/web/templates/default/base.html:39 -msgid "pyLoad Update available!" +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" msgstr "" -#: module/web/templates/default/base.html:46 -msgid "Plugins updated, please restart!" +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" msgstr "" -#: module/web/templates/default/base.html:52 -msgid "Captcha waiting" +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" msgstr "" -#: module/web/templates/default/base.html:57 -msgid "Logout" +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" msgstr "" -#: module/web/templates/default/base.html:61 -msgid "Info" +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" msgstr "" -#: module/web/templates/default/base.html:65 -msgid "Please Login!" +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" msgstr "" -#: module/web/templates/default/base.html:84 -#: module/web/templates/default/home.html:211 -msgid "Home" +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." msgstr "" -#: module/web/templates/default/base.html:87 -#: module/web/templates/default/queue.html:15 -#: module/web/templates/default/window.html:34 -#: module/web/templates/default/home.html:214 -msgid "Queue" +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." msgstr "" -#: module/web/templates/default/base.html:90 -#: module/web/templates/default/queue.html:17 -#: module/web/templates/default/window.html:36 -#: module/web/templates/default/home.html:217 -msgid "Collector" +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" msgstr "" -#: module/web/templates/default/base.html:99 -#: module/web/templates/default/logs.html:3 -#: module/web/templates/default/logs.html:4 -#: module/web/templates/default/home.html:226 -msgid "Logs" +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." msgstr "" -#: module/web/templates/default/base.html:114 -#: module/web/templates/default/logs.html:12 -msgid "Start" +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" msgstr "" -#: module/web/templates/default/base.html:115 -msgid "Stop" +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" msgstr "" -#: module/web/templates/default/base.html:116 -msgid "Cancel" +#: module/webui/themes/default/tml/window.html:26 +msgid "File" msgstr "" -#: module/web/templates/default/base.html:123 -msgid "Download:" +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." msgstr "" -#: module/web/templates/default/base.html:124 -msgid "Reconnect:" +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" msgstr "" -#: module/web/templates/default/base.html:125 -msgid "Speed:" +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" msgstr "" -#: module/web/templates/default/base.html:126 -msgid "Active:" +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" msgstr "" -#: module/web/templates/default/base.html:127 -msgid "Reload page" +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." msgstr "" -#: module/web/templates/default/base.html:157 -msgid "loading" +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" msgstr "" -#: module/web/templates/default/base.html:166 -msgid "Back to top" +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." msgstr "" -#: module/web/templates/default/logs.html:12 -msgid "prev" +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" msgstr "" -#: module/web/templates/default/logs.html:12 -msgid "next" +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" msgstr "" -#: module/web/templates/default/logs.html:12 -msgid "End" +#: module/webui/themes/default/tml/base.html:39 +#, python-format +msgid "New pyLoad version %s available!" msgstr "" -#: module/web/templates/default/logout.html:8 -msgid "You were successfully logged out." +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" msgstr "" -#: module/web/templates/default/queue.html:25 -msgid "Delete Finished" +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" msgstr "" -#: module/web/templates/default/queue.html:26 -msgid "Restart Failed" +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" msgstr "" -#: module/web/templates/default/queue.html:65 -msgid "Folder:" +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" msgstr "" -#: module/web/templates/default/queue.html:65 -msgid "Password:" +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" msgstr "" -#: module/web/templates/default/queue.html:79 -msgid "Edit Package" +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" msgstr "" -#: module/web/templates/default/queue.html:80 -msgid "Edit the package detais below." +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" msgstr "" -#: module/web/templates/default/queue.html:83 -msgid "The name of the package." +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" msgstr "" -#: module/web/templates/default/queue.html:87 -msgid "Folder" +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" msgstr "" -#: module/web/templates/default/queue.html:88 -msgid "Name of subfolder for these downloads." +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" msgstr "" -#: module/web/templates/default/queue.html:93 -msgid "List of passwords used for unrar." +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" msgstr "" -#: module/web/templates/default/window.html:5 -#: module/web/templates/default/window.html:40 -msgid "Add Package" +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" msgstr "" -#: module/web/templates/default/window.html:6 -msgid "Paste your links or upload a container." +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" msgstr "" -#: module/web/templates/default/window.html:8 -msgid "The name of the new package." +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" msgstr "" -#: module/web/templates/default/window.html:12 -msgid "Links" +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" msgstr "" -#: module/web/templates/default/window.html:13 -msgid "Paste your links here or any text and press the filter button." +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" msgstr "" -#: module/web/templates/default/window.html:14 -msgid "Filter urls" +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" msgstr "" -#: module/web/templates/default/window.html:22 -msgid "Password for RAR-Archive" +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" msgstr "" -#: module/web/templates/default/window.html:26 -msgid "File" +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" msgstr "" -#: module/web/templates/default/window.html:27 -msgid "Upload a container." +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" msgstr "" -#: module/web/templates/default/window.html:31 -msgid "Destination" +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" msgstr "" -#: module/web/templates/default/home.html:206 -msgid "Active Downloads" +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" msgstr "" -#: module/web/templates/default/home.html:240 -msgid "Size" +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" msgstr "" -#: module/web/templates/default/home.html:241 -msgid "Progress" +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." msgstr "" -#: module/web/templates/default/captcha.html:6 -msgid "Captcha reading" +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" msgstr "" -#: module/web/templates/default/captcha.html:13 -msgid "Captcha" +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" msgstr "" -#: module/web/templates/default/captcha.html:14 -msgid "The captcha." +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" msgstr "" -#: module/web/templates/default/captcha.html:20 -msgid "Text" +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." msgstr "" -#: module/web/templates/default/captcha.html:21 -msgid "Input the text on the captcha." +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" msgstr "" -#: module/web/templates/default/captcha.html:34 -msgid "Close" +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:127 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:195 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:264 module/webui/app/pyload.py:271 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:509 +msgid "Run pyload.py -s to access the setup." msgstr "" diff --git a/locale/el/LC_MESSAGES/django.po b/locale/el/LC_MESSAGES/django.po new file mode 100644 index 000000000..f292fcb89 --- /dev/null +++ b/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Greek\n" +"Language: el_GR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "ÎίÏηÏη για ΜÎο Captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÎŽÎ¹Î±Î²Î¬ÏÏε Ïο κείΌεΜο ÏÏο captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "ÎγιΜε εÏαΜεκκίΜηÏη ÏÏο pyLoad " + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "αΜεΜεÏγÏ" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "ÎÏιÏÏ
Ïία" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "εΜεÏγÏ" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "ÎίÏÏε ÏίγοÏ
Ïοι ÏÏι ΞÎλεÏε Μα ÏεÏΌαÏίÏεÏε Ïο pyLoad ;" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "ÎÏαΜεκκίΜηÏη ÏÏ
ΜΎÎÏΌοÏ
" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "ÎιαγÏαÏή ÏÏ
ΜΎÎÏΌοÏ
" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÎµÎ¹ÏάγεÏε ÎΜα ÏΜοΌα για Ïο ÏακÎÏο" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÏαÏήÏÏε ÏÏη ÏÏÏÏή ΞÎÏη captcha" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "ΠαÏοÏ
ÏιάÏÏηκε ÎΜα ÏÏάλΌα" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Î ÏÎ¬ÎºÎµÎ»Î¿Ï ÎµÎ¯ÎœÎ±Î¹ άΎειοÏ" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "ÎÏÎÏÏ
ÏαΜ" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "ÎεΜ Ï
ÏάÏÏοÏ
Μ Captchas για αΜάγΜÏÏη." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Îι κÏΎικοί ΎεΜ ÏαιÏιάζοÏ
Μ" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Îι ÏÏ
ΞΌίÏÎµÎ¹Ï Î±ÏοΞηκεÏÏηκαΜ" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "ÎÎÎ¿Ï ÏάκελοÏ" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "ÎίÏαÏÏε ÏίγοÏ
Ïοι ÏÏι ΞÎλεÏε Μα κάΜεÏε εÏαΜεκκίΜηÏη ÏÏο pyLoad ;" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "αΜαΌοΜή %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "ÎΜεÏγÎÏ ÎεÏαÏοÏÏÏÏÎµÎ¹Ï " + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "ÎÏÏική" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "ÎήÏειÏ" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "ÎÏÏεία καÏαγÏαÏήÏ" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "ΡÏ
ΞΌίÏειÏ" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "ÎΜοΌα" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "ÎαÏάÏÏαÏη" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "ΠληÏοÏοÏία" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "ÎÎγεΞοÏ" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Î ÏÏοΎοÏ" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "ΣÏΜΎεÏη" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "ÎΜοΌα ΧÏήÏÏη" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "ÎÏΎικÏÏ ÏÏÏÏβαÏηÏ" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "΀ο ÏΜοΌα ÏÏήÏÏη και ο κÏΎικÏÏ ÏÏÏÏβαÏÎ·Ï ÎŽÎµÎœ ÏαιÏιάζοÏ
Μ. ÎοκιΌάÏÏε ΟαΜά." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Îια Μα εÏαΜαÏÎÏεÏε Ïα ÏÏοιÏεία ειÏÏΎοÏ
ή για Μα ÏÏοÏΞÎÏÏε ÏÏήÏÏη ÏÏÎΟÏε: " + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "ÎιαγÏαÏή ΀ελείÏÏε" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "ÎÏαΜεκκίΜηÏη ÎÏÎÏÏ
Ïε" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "ΊάκελοÏ:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "ÎÏΎικÏÏ Î ÏÏÏβαÏηÏ:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "ÎÏεΟεÏγαÏία ΠακÎÏοÏ
" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "ÎÏεΟεÏγαÏÏείÏε λεÏÏοΌÎÏÎµÎ¹ÎµÏ ÏοÏ
ÏακÎÏοÏ
ÏαÏακάÏÏ. " + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "΀ο ÏΜοΌα ÏοÏ
ÏακÎÏοÏ
." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "ΊάκελοÏ" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "ÎΜοΌα Ï
ÏοÏακÎλοÏ
για αÏ
ÏÎÏ ÏÎ¹Ï ÎŒÎµÏαÏοÏÏÏÏειÏ." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "ÎίÏÏα κÏΎικÏΜ ÏοÏ
ÏÏηÏιΌοÏοιοÏΜÏαι για Ïο unrar." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Î¥Ïοβολή" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "ÎÏαΜαÏοÏά" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "ÎÏοÏÏ
ΜΎεΞήκαÏε εÏιÏÏ
ÏήÏ." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "ÎιαΎÏοΌή" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "αÏÏλÏ
Ïη" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "ÏÏεÏική" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "ÏΜοΌα" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "ÎŒÎγεΞοÏ" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "ÏÏÏοÏ" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "ÏελεÏ
Ïαία αλλαγή" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "γοΜικÏÏ ÏάκελοÏ" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "ÏÏÏÎ¯Ï ÏεÏιεÏÏΌεΜο" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "ÎεΜικά" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Î ÏÏÏΞεÏα" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "ÎογαÏιαÏΌοί" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "ÎÏιλÎΟÏε αÏÏ Ïο menu" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Î ÏÏÏΞεÏα" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "ÎγκÏ
Ïο εÏÏ" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "ÎΜαÏοΌείΜοÏ
Ïα κίΜηÏη" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "ΧÏÏΜοÏ" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "ÎÎγιÏÏÎ¿Ï Î±ÏιΞΌÏÏ ÏαÏ
ÏÏÏÏοΜÏΜ" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "ÎιαγÏαÏή;" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "ÎγκÏ
Ïο" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "άκÏ
Ïο" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "Μαι" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "ÏÏι" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Î ÏοÏΞήκη" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Î ÏοÏΞήκη ÎογαÏιαÏΌοÏ" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "ÎιÏάγεÏε Ïα ÏÏοιÏεία ÏοÏ
λογαÏιαÏÎŒÎ¿Ï ÏÎ±Ï Î³Î¹Î± Μα ÏÏηÏιΌοÏοιήÏεÏε Ïα εÏιÏλÎοΜ ÏαÏακÏηÏιÏÏικά." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "΀ο ÏΜοΌα ÏÏήÏÏη ÏαÏ." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "ΠκÏΎικÏÏ ÏÏήÏÏÎ·Ï Î³Î¹Î± αÏ
ÏÏΜ Ïο λογαÏιαÏÎŒÏ." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "΀ÏÏοÏ" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "ΧÏηÏιΌοÏοιήÏÏε άλλο hoster για ÏοΜ λογαÏιαÏÎŒÏ ÏαÏ. " + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "ÎκκίΜηÏη" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "ÏÏοηγ." + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "εÏÏÎŒ." + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "΀ÎλοÏ" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "ÎÎα" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Î¥ÏοÏÏήÏιΟη" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "ΣÏÏÏηΌα" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "ÎκΎοÏη pyLoad: " + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "ÎŠÎ¬ÎºÎµÎ»Î¿Ï ÎγκαÏάÏÏαÏηÏ: " + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "ÎŠÎ¬ÎºÎµÎ»Î¿Ï Î¡Ï
ΞΌίÏεÏΜ: " + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "ÎŠÎ¬ÎºÎµÎ»Î¿Ï ÎήÏηÏ: " + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "ÎλεÏΞεÏÎ¿Ï Î§ÏÏοÏ: " + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "ÎλÏÏÏα: " + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "ÎÏÏα Webinterface: " + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "ÎÏÏα ÎÏοΌακÏÏ
ÏÎŒÎÎœÎ·Ï Î ÏÏÏβαÏηÏ: " + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "ÎγκαÏάÏÏαÏη" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "ÎιαÏείÏιÏη ÎÏÏείÏΜ" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Î ÏοÏΞήκη ΠακÎÏοÏ
" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "ÎÏικολλήÏÏε ÏÏ
ΜΎÎÏΌοÏ
Ï Î· ÏοÏÏÏÏÏε αÏÏείο container." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "΀ο ÏΜοΌα ÏοÏ
ΜÎοÏ
ÏακÎÏοÏ
." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "ΣÏΜΎεÏΌοι" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "ÎÏικολλήÏÏε ÏοÏ
Ï ÏÏ
ΜΎÎÏΌοÏ
Ï ÏÎ±Ï ÎµÎŽÏ Î® οÏοιοΎήÏοÏε κείΌεΜο και ÏαÏήÏÏε Ïο ÏλήκÏÏο ÏίλÏÏοÏ
." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "ΊιλÏÏάÏιÏΌα urls" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "ÎÏΎικÏÏ Î³Î¹Î± AÏÏείο RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "AÏÏείο" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "ÎΜεβάÏÏε αÏÏείο container." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Î ÏοοÏιÏÎŒÏÏ" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "ÎΜάλÏ
Ïη Captcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "΀ο captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "ÎείΌεΜο" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "ÎιÏάγεÏε Ïο κείΌεΜο ÏοÏ
ÏαίΜεÏαι ÏÏο captcha." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "ÎλείÏιΌο" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "ÎιεÏαÏή ιÏÏοÏ" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "Î¥ÏάÏÏει ΎιαΞÎÏιΌη αΜαβάΞΌιÏη για Ïο pyLoad!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "΀α ÏÏÏÏΞεÏα αΜαβαΞΌίÏÏηκαΜ, ÏαÏακαλοÏΌε κάΜÏε εÏαΜεκκίΜηÏη!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "ΠεÏιΌÎΜει Captcha" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "ÎÏοÏÏΜΎεÏη" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "ÎιαÏείÏιÏη" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "ΠληÏοÏοÏίεÏ" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï Î£Ï
ΜΎεΞείÏε!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "ÎιακοÏή" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "ÎκÏÏÏÏη" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "ÎήÏη:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "ÎÏαΜαÏÏΜΎεÏη:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "΀αÏÏÏηÏα:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "ÎΜεÏγÏ:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "ÎÏαΜαÏÏÏÏιÏη ÏελίΎαÏ" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "ÏοÏÏÏΜει " + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "ÎÏιÏÏÏοÏή ÏÏηΜ κοÏÏ
Ïή" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "ΣÏαΌάÏηΌα ÏοÏ
pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "ÎÏαΜεκκίΜηÏη ÏοÏ
pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Îια Μα ÏÏοÏΞÎÏεÏε ÏÏήÏÏÎµÏ Î® Μα αλλάΟεÏε κÏΎικοÏÏ ÏÏÏÏβαÏÎ·Ï ÏÏηÏιΌοÏοιήÏεÏε: " + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "ÎÏιÏήΌαΜÏη: Î ÎιαÏειÏιÏÏÎ®Ï ÎÏει ÏάΜÏα Ïλα Ïα ΎικαιÏΌαÏα!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Îλλαγή ÎÏÎŽÎ¹ÎºÎ¿Ï Î ÏÏÏβαÏηÏ" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "ÎιαÏειÏιÏÏήÏ" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "ÎικαιÏΌαÏα" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "αλλαγή" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "ÎιÏάγεÏε Ïο ÏαÏÏΜ και Ïο εÏιΞÏ
ΌηÏÏ ÎºÏÎŽÎ¹ÎºÏ ÏÏήÏÏη." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "ÎΜοΌα ÏÏήÏÏη" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "ΠαÏÏΜ κÏΎικÏÏ ÏÏήÏÏη" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "ÎÎÎ¿Ï ÎºÏΎικÏÏ ÏÏήÏÏη" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "ΠΜÎÎ¿Ï ÎºÏΎικÏÏ ÏÏήÏÏη." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "ÎÎÎ¿Ï ÎºÏΎικÏÏ ÏÏήÏÏη (εÏαΜάληÏη)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÎµÏαΜαλάβεÏε Ïο ΜÎο κÏÎŽÎ¹ÎºÏ ÏÏήÏÏη." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "ÎεΜ ÏÎ±Ï ÎµÏιÏÏÎÏεÏε η ÏÏÏÏβαÏη Ïε αÏ
Ïή Ïη ÏελίΎα" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "ΠκαÏÎ¬Î»Î¿Î³Î¿Ï ÎŒÎµÏαÏοÏÏÏÏεÏΜ ΎεΜ βÏÎΞηκε" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "αÏεÏιÏÏιÏÏο" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "Όη ΎιαΞÎÏιΌο" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÎκÏελÎÏÏε ÏηΜ εΜÏολή pyload.py -s για ÏÏÏÏβαÏη ÏÏηΜ εγκαÏάÏÏαÏη." + diff --git a/locale/el/LC_MESSAGES/pyLoad.po b/locale/el/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..c292ac965 --- /dev/null +++ b/locale/el/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Greek\n" +"Language: el_GR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "ÎλήÏΞη ÏήΌα εγκαÏάλειÏηÏ" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "΀ο pyLoad εκÏελείÏαι ήΎη Όε pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "ÎÏοÏÏ
Ïία Î±Î»Î»Î±Î³Î®Ï Î¿ÎŒÎ¬ÎŽÎ±Ï: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "ÎÏοÏÏ
Ïία Î±Î»Î»Î±Î³Î®Ï ÏÏήÏÏη: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "ÏÎ¬ÎºÎµÎ»Î¿Ï Î³Î¹Î± αÏÏεία καÏαγÏαÏήÏ" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Σε εκκίΜηÏη" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "ΧÏήÏη Î³Î¿ÎœÎ¹ÎºÎ¿Ï ÎºÎ±ÏαλÏγοÏ
: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "Ïο pycrypto Ξα αÏοκÏΎικοÏοιήÏει Ïα ÏεÏιÎÏοΜÏα αÏÏεία" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "ÏÎ¬ÎºÎµÎ»Î¿Ï Î³Î¹Î± ÏÏοÏÏÏιΜά αÏÏεία" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "ÏÎ¬ÎºÎµÎ»Î¿Ï Î³Î¹Î± καÏεβαÏÎŒÎΜα" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL για αÏÏαλή ÏÏΜΎεÏη" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÎµÎ»ÎγΟÏε Ïα ÏÏοιÏεία ÏÏΜΎεÏÎ·Ï ÎŒÎµ Ïη ÏÏήÏη ÏοÏ
./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Îλοι οι ÏÏ
ΜΎεÏΌοι αÏαιÏÎΞηκαΜ" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "ΧÏÏÎœÎ¿Ï ÎºÎ±ÏεβάÏΌαÏοÏ: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "ÎλÎÏ
ΞεÏÎ¿Ï ÏÏÏÎ¿Ï ÏÏο ΎίÏκο: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "ÎΜεÏγοÏοίηÏη ÎογαÏιαÏÎŒÏΜ..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "ÎΜεÏγοÏοίηÏη Î ÏÏÏΞεÏÏΜ..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "΀ο pyLoad είΜαι εΜεÏÎ³Ï ÎºÎ±Î¹ εκÏελείÏαι " + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "Ïο pyLoad εÏαΜεκκιΜείÏαι" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "Ïο pyLoad ÏÏαΌαÏάει" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "ÎγκαÏάÏÏαÏη %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "ΎεΜ βÏεΞηκε(καΜ) %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "ΎεΜ ΎιΌιοÏ
ÏγήΞηκε(καΜ) %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "κλείÏιΌο..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "ÏÏάλΌα καÏα Ïο κλείÏιΌο" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "Ïο pyLoad ÏÏαΌαÏήΞηκε αÏο Ïο ΀εÏΌαÏικο" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "ÏελείÏÏε" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "αÏοÏÏ
ΜΎεΌÎΜοÏ" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "ÏÏ
ΜΎεΌÎΜοÏ" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "ÏÏηΜ οÏ
Ïά" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "ÏÏοÏÏεÏάÏÏηκε" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "Ïε αΜαΌοΜή" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "ÏÏοÏÏÏιΜά ÏÏÏÎ¯Ï ÏÏΜΎεÏη" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "ΟεκιΜάει" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "αÏÎÏÏ
Ïε" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "ΌαÏαιÏΞηκε" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "αÏοκÏÏ
ÏÏογÏαÏείÏαι" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "ÏÏοÏαÏΌοÏÎŒÎΜο" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "Ïε λήÏη" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "Ïε εΟÎλιΟη" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "άγΜÏÏÏο" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "ÎλοκλήÏÏÏη ÏακÎÏοÏ
: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "ΣÏάλΌα αÏοΌακÏÏ
ÏÎŒÎΜοÏ
backend: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "ÎίΜεÏαι εκκίΜηÏη %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "ÎÏÎÏÏ
Ïε η ÏÏÏÏÏÏη ÏοÏ
backend %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "αΜαΌοΜή %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "ÎεΜ βÏÎΞηκαΜ ÏιÏÏοÏοιηÏικά SSL." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "ÎÏοÏείÏε Μα ÏÏηÏιΌοÏοιήÏεÏε ÏοΜ threaded server ÏοÏ
ÏÏοÏÏÎÏει καλή αÏÏΎοÏη και ssl," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "ÏαÏαΎείγΌαÏα αÏÏείÏΜ ÏÏ
ΞΌίÏεÏΜ βÏίÏκοΜÏαι ÎŒÎÏα ÏÏο Ïάκελο module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "ÎÏοÏÏ
Ïία ÏÏήÏÎ·Ï ÏοÏ
%(server)s, ΎεΜ είΜαι εγκαÏεÏÏηΌÎΜο Ïο ÏακÎÏο python-flup!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "ΧÏειάζεÏαι Μα καÏεβλαÏεÏε και Μα ÏÏ
ΜÏάΟεÏε Ïο bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Îα ÏÏ
Ïικά και ÏÏειάζεÏε Μα είÏÏε Î¿Î¹ÎºÎµÎ¯Î¿Ï ÎŒÎµ Ïα linux και Μα ΟÎÏεÏε ÏÏÏ ÎœÎ± ÏÏ
ΜÏάÏÏεÏαι λογιÏΌικÏ" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "ΠΎιακοΌιÏÏÎ®Ï Î¬Î»Î»Î±ÎŸÎµ Ïε threaded, λÏÎ³Ï ÎºÎ¬ÏοιÏΜ γΜÏÏÏÏΜ ÏÏοβληΌάÏÏΜ αÏÏΎοÏÎ·Ï ÏÏα windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "ÎÏ
ÏÏÏ Î¿ ΎιακοΌιÏÏÎ®Ï ÎŽÎµÎœ ÏÏοÏÏÎÏει SSL, αΜÏί για αÏ
ÏÏΜ ÏαÏÎ±ÎºÎ±Î»Ï ÏκεÏÏείÏε ÏηΜ ÏεÏίÏÏÏÏη ÏÏήÏÎ·Ï ÏοÏ
threaded" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "ÎκκίΜηÏη ÏοÏ
εΜÏÏΌαÏÏÎŒÎΜοÏ
ΎιακοΌιÏÏή web: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "ÎκκίΜηÏη ÏοÏ
threaded SSL ΎιακοΌιÏÏή web: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "ÎκκίΜηÏη ÏοÏ
threaded ΎιακοΌιÏÏή web: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "ÎκκίΜηÏη ÏοÏ
ΎιακοΌιÏÏή fastcgi: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "ÎεΜ ÏÎ±Ï ÎµÏιÏÏÎÏεÏε η ÏÏÏÏβαÏη Ïε αÏ
Ïή Ïη ÏελίΎα" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "ΠκαÏÎ¬Î»Î¿Î³Î¿Ï ÎŒÎµÏαÏοÏÏÏÏεÏΜ ΎεΜ βÏÎΞηκε" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "αÏεÏιÏÏιÏÏο" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "Όη ΎιαΞÎÏιΌο" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÎκÏελÎÏÏε ÏηΜ εΜÏολή pyload.py -s για ÏÏÏÏβαÏη ÏÏηΜ εγκαÏάÏÏαÏη." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "ΠλήÏη ÏÏΜ κοΌΌαÏιÏΜ αÏÎÏÏ
Ïε, εÏιÏÏÏοÏή Ïε καÏάÏÏαÏη ÎŒÎ¿ÎœÎ®Ï ÏÏΜΎεÏÎ·Ï | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "ΠλήÏη ΟεκιΜά: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "ΠλήÏη ολοκληÏÏΞηκε: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "ΣÏο ÏÏÏÏΞεÏο %s λείÏει Όια λειÏοÏ
Ïγία." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "ΠλήÏη ΌαÏαιÏΞηκε: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "ΠλήÏη εÏαΜεκκιΜήΞηκε: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "ΠλήÏη είΜαι εκÏÏÏ ÏÏΜΎεÏηÏ: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "ΠλήÏη είΜαι ÏÏοÏÏÏιΜά εκÏÏÏ ÏÏΜΎεÏηÏ: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "ΠλήÏη αÏÎÏÏ
Ïε: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "ÎÏοÏÏ
Ïία ÏÏΜΎεÏÎ·Ï ÎŒÎµ Ïο ΎιακοΌιÏÏή ή ΎιακοÏή ÏÏΜΎεÏηÏ, αΜαΌοΜή 1 λεÏÏÏ ÏÏιΜ γίΜει κι άλλη ÏÏοÏÏάΞεια." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "ÎγιΜε ÏαÏάλειÏη ÏÏη λήÏη: %(name)s εΟαιÏÎ¯Î±Ï ÏοÏ
%(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "ΠαΜάκÏηÏη ÏληÏοÏοÏιÏΜ για Ïο %(name)s αÏÎÏÏ
Ïε | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "ÎÏοÏÏ
Ïία εΜεÏγοÏοίηÏÎ·Ï %(name)s " + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "ÎΜεÏγοÏοιηΌÎΜα ÏÏÏÏΞεÏα: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "ÎÏεΜεÏγοÏοίηÏη ÏÏÏÏΞεÏÏΜ: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "ÎÏαΜαÏÏΜΎεÏη αÏÎÏÏ
Ïε %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "ÎεΜ βÏÎΞηκε αÏÏείο εΜÏολÏΜ για εÏαΜαÏÏΜΎεÏη!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "ÎεκιΜάει η εÏαΜαÏÏΜΎεÏη" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "ÎÏοÏÏ
Ïία εκÏÎλεÏÎ·Ï Î±ÏÏείοÏ
εΜÏολÏΜ εÏαΜαÏÏΜΎεÏηÏ!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "ÎÏαΜαÏÏ
ΜΎÎΞηκε, ΜÎα ΎιÎÏ
ΞÏ
ΜÏη IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "ÎεΜ ÎÏει αÏοΌείΜει αÏκεÏÏÏ ÏÏÏÎ¿Ï ÏÏηΜ ÏÏ
ÏκεÏ
ή" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "ÎÏοÏÏ
Ïία ÏÏΜΎεÏÎ·Ï ÎŒÎµ ÏοΜ λογαÏιαÏÎŒÏ %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "ÎÎ¬ÎžÎ¿Ï ÎºÏΎικÏÏ" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "ΣÏοΜ λογαÏιαÏÎŒÏ %s ΎεΜ ÎÏει αÏοΌείΜει αÏκεÏή κίΜηÏη ΎεΎοΌÎΜÏΜ, Ξα γίΜει Ïάλι ÎλεγÏÎ¿Ï Ïε 30 λεÏÏά" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "ΠλογαÏιαÏÎŒÏÏ %s ÎÏει λήΟει, Ξα γίΜει ΟαΜά ÎλεγÏÎ¿Ï Ïε 1 ÏÏα" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "ΊÏάÏαÏε ÏÏο ÎŒÎγιÏÏο ÏÏιο λήÏεÏΜ" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "ΣÏάλΌα καÏά ÏηΜ ειÏαγÏγή %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "ÎεΜ ÏοÏÏÏΞηκε κάÏÎ¿Î¹Î¿Ï hoster" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "ÎΜεÏγοÏοιήÏÏε ÏÎ¹Ï Î±ÏεÏ
ÎžÎµÎ¯Î±Ï Î»Î®ÏÎµÎ¹Ï ÏÏοΜ Bitshare λογαÏιαÏÎŒÏ ÏαÏ" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "ÎÏαιÏείÏαι ÏιÏÏοÏοίηÏη (ÏΜοΌα ÏÏήÏÏη:κÏΎικÏÏ)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÎµÎ¹ÏάγεÏε Ïο λογαÏιαÏÎŒÏ ÏÎ±Ï %s ή αÏεΜεÏγοÏοιήÏÏε αÏ
ÏÏ Ïο ÏÏÏÏΞεÏο" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "Î¥ÏήÏÏε κÏÎŽÎ¹ÎºÎ±Ï HTML ÏÏο αÏÏείο ÏοÏ
ΌεÏαÏοÏÏÏΞηκε (%s)...ÏÏÏβληΌα αΜακαÏεÏΞÏ
ΜÏÎ·Ï Î¯ÏÏÏ; ΠΌεÏαÏÏÏÏÏÏη Ξα εÏαΜεκκιΜήÏει." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "΀ο αÏÏείο είΜαι ÏÏοÏÏÏιΜά Όη ΎιαΞÎÏιΌο" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: αΜαΌοΜή ΌεÏÎ±ÎŸÏ ÏÏΜ λήÏεÏΜ %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: αΜαΌοΜή για captcha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "΀ο ληÏΞÎΜ αÏÏείο ήÏαΜ άΎειο" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "΀ο κλειΎί API ΎεΜ είΜαι ÎγκÏ
Ïο" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: ÎεΜ αÏÎΌειΜε αÏκεÏή κίΜηÏη ΎεΎοΌÎΜÏΜ" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Î¥ÏÎÏβαÏη οÏίοÏ
κίΜηÏÎ·Ï ÎŽÎµÎŽÎ¿ÎŒÎΜÏΜ" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Traffic Share (αÏεÏ
ÎžÎµÎ¯Î±Ï Î»Î®Ïη)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "ÎαÏεβάζεÏε ήΎη αÏÏ Î±Ï
Ïή Ïη ΎιεÏΞÏ
ΜÏη ÎΡ, αΜαΌοΜή 60 ΎεÏ
ÏεÏολÎÏÏÏΜ" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Îη ÎγκÏ
ÏÎ¿Ï ÎºÏÎŽÎ¹ÎºÎ±Ï , η λήÏη Ξα γίΜει εÏαΜεκκίΜηÏη" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: ÎεΜ Ï
ÏάÏÏοÏ
Μ ελÎÏ
ΞεÏα slots" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "ΧÏειάζεÏÏε ÎΜαΜ λογαÏιαÏÎŒÏ premium για αÏ
ÏÏ Ïο αÏÏείο" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "΀ο ÏΜοΌα αÏÏείοÏ
αΜαÏÎÏΞηκε ÏÏ ÎŒÎ· ÎγκÏ
Ïο" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "ΣÏάλΌα ÏαÏ
ÏÏÏÏÎ¿ÎœÎ·Ï Î»Î®ÏηÏ, αΜαΌοΜή 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "ÎεΜ ÎÏεÏε ÏÏ
ΜΎεΞεί." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "ΠαÏοκÏÏ
ÏÏογÏάÏηÏη αÏÎÏÏ
Ïε" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "ΠΎιεÏΞÏ
ΜÏη URL ΎεΜ ÏαÏείÏε καΜÎΜα κλειΎί αÏÏείοÏ
" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "ÎÏΎικÏÏ ÏÏάλΌαÏοÏ:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "΀ο αÏÏείο ΎεΜ Ï
ÏάÏÏει" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** ΀α ÏÏÏÏΞεÏα ÎÏοÏ
Μ αΜαβαΞΌιÏÏεί, ÏαÏÎ±ÎºÎ±Î»Ï ÎµÏαΜεκκιΜήÏÏε Ïο pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "΀α ÏÏÏÏΞεÏα αΜαβαΞΌίÏÏηκαΜ και ΟαΜαÏοÏÏÏΞηκαΜ" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "ÎεΜ Ï
ÏάÏÏοÏ
Μ αΜαβαΞΌίÏÎµÎ¹Ï Î³Î¹Î± Ïα ÏÏÏÏΞεÏα" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "ÎεΜ βÏÎΞηκε αΜαβάΞΌιÏη για Ïο pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** ÎίΜαι ΎιαΞÎÏιΌη Όια καιΜοÏÏια ÎκΎοÏη (%s) ÏοÏ
pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** ÎαÏεβάÏÏε αÏο εΎÏ: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "ÎÎŽÏ
ΜαΌία ÏÏΜΎεÏÎ·Ï ÏÏοΜ κεΜÏÏÎ¹ÎºÏ ÎŽÎ¹Î±ÎºÎ¿ÎŒÎ¹ÏÏή για ÎλεγÏο εΜηΌεÏÏÏεÏΜ" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "ÎÎα ÎκΎοÏη ÏοÏ
%(type)s | %(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "ΣÏάλΌα καÏά ÏηΜ αΜαβάΞΌιÏη ÏοÏ
%s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "ÎÏÏ
ÎŒÏÏΜία ÎκΎοÏηÏ" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "ΠλήÏη ολοκληÏÏΞηκε: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "ÎίÏηÏη για ΜÎο Captcha: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "ÎÏάΜÏηÏη Όε 'c %s κείΌεΜο για Ïο captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÏÏοÏΞÎÏÏε ÏÏÏÏα ÏοΜ λογαÏÎ¹Î±ÎŒÏ ÏÎ±Ï ÏÏο premium.to και εÏαΜεκκιΜήÏÏε Ïο pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Î ÏοÏÏÎΞηκε Ïο %s αÏÏ HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "ÎεΜ ÎÏει εγκαÏαÏÏαΞεί Ïο %s" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "ÎÏοÏÏ
Ïία εΜεÏγοÏοίηÏÎ·Ï ÏοÏ
%s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "ÎΜεÏγοÏοιήΞηκε" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "ÎεΜ ÎÏοÏ
Μ εΜεÏγοÏοιηΞεί ÏÏÏÏΞεÏα για αÏοÏÏ
ÎŒÏίεÏη" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "΀ο ÏακÎÏο %s ÎÏει ÎŽÏοΌολογηΞεί για αÏοÏÏ
ÎŒÏίεÏη αÏγÏÏεÏα" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "ÎλεγÏÎ¿Ï ÏοÏ
ÏακÎÏοÏ
%s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "ÎÏοÏÏ
ÎŒÏίεÏη ÏÏο %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "ÎεΜ βÏÎΞηκαΜ αÏÏεία για αÏοÏÏ
ÎŒÏίεÏη" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "αÏοÏÏ
ÎŒÏιÎζεÏαι" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Î ÏοÏÏαÏεÏ
ÎŒÎΜο Όε κÏΎικÏ" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "ÎÎ¬ÎžÎ¿Ï ÎºÏΎικÏÏ" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "ÎιαγÏαÏή %s αÏÏείÏΜ" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "ΠαÏοÏÏ
ÎŒÏίεÏη ÏελείÏÏε" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "ΣÏάλΌα ÏÏο ÏÏ
ÎŒÏιεÏÎŒÎΜο αÏÏείο" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "ÎÏÏ
ÎŒÏÏΜία CRC" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "ÎγΜÏÏÏο ΣÏάλΌα" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "ΠοÏιÏÎŒÏÏ ÏοÏ
ΧÏήÏÏη και ÏÎ·Ï ÎÎŒÎ¬ÎŽÎ±Ï Î±ÏÎÏÏ
ÏαΜ" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: ΠΞÏÏα 9666 ÏÏηÏιΌοÏοιείÏαι ήΎη" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "αÏοΌÎΜοÏ
Μ %s ÏÏΜÏοι" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "ÎÏοÏÏ
Ïία αÏοÏÏÎ¿Î»Î®Ï Î±ÏάΜÏηÏηÏ." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "ΠλογαÏιÏÎŒÏÏ ÏÎ±Ï CaptchaTrader ΎεΜ ÎÏει αÏκεÏοÏÏ ÏÏΜÏοÏ
Ï" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "ΠλίÏÏα Crypter ΎεΜ βÏÎΞηκε" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "ΠλίÏÏα Crypter είΜαι κεΜή" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "ΠλήÏη ολοκληÏÏΞηκε: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "ÎÎο CaptchaID αÏÏ Ïη ΌεÏαÏÏÏÏÏÏη: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "ΠλογαÏιαÏÎŒÏÏ ÏÎ±Ï Captcha 9kw.eu ΎεΜ ÎÏει αÏκεÏοÏÏ ÏÏΜÏοÏ
Ï" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "ÎγκαÏεÏÏηΌÎΜα αÏÏεία εΜÏολÏΜ για Ïο %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "΀ο αÏÏείο εΜÏολÏΜ ΎεΜ είΜαι εκÏελÎÏιΌο:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "ΣÏάλΌα ÏÏο %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "ΠλογαÏιαÏÎŒÏÏ ÏÏο ExpertDecoders ΎεΜ ÎÏει αÏκεÏοÏÏ ÏÏΜÏοÏ
Ï" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÏÏοÏΞÎÏÏε ÏÏÏÏα ÏοΜ λογαÏÎ¹Î±ÎŒÏ ÏÎ±Ï ÏÏο rehost.to και εÏαΜεκκιΜήÏÏε Ïο pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÏÏοÏΞÎÏÏε ÏÏÏÏα ÎΜαΜ ÎγκÏ
Ïο λογαÏÎ¹Î±ÎŒÏ ÏÏο premiumize.me και εÏαΜεκκιΜήÏÏε Ïο pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "αÏοΌÎΜοÏ
Μ %d ÏÏΜÏοι" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "΀ο PIL και Ïο tesseract ΎεΜ είΜαι εγκαÏαÏÏηΌÎΜα και ΎεΜ Ï
ÏάÏÏει ÏÏÏγÏαΌΌα-ÏελάÏÎ·Ï ÏÏ
ΜΎεΌÎÎœÎ¿Ï Î³Î¹Î± αÏοκÏÏ
ÏÏογÏάÏηÏη captcha" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Î ÏÏΞΌιÏη ÏÏηÏÏÏΜ και οΌάΎÏΜ αÏÎÏÏ
Ïε: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Î ÏοÏÏÎΞηκαΜ %(count)d ÏÏΜΎεÏΌοι ÏÏο ÏακÎÏο #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "ÎαΌία ΌηÏαΜή js ΎεΜ βÏÎΞηκε, ÏαÏÎ±ÎºÎ±Î»Ï ÎµÎ³ÎºÎ±ÏαÏÏήÏεÏε Όια αÏο ÏÎ¹Ï ÏαÏακάÏÏ Spidermonkey, ossp-js, pyv8, rhino " + diff --git a/locale/el/LC_MESSAGES/pyLoadCli.po b/locale/el/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..52d49be62 --- /dev/null +++ b/locale/el/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Greek\n" +"Language: el_GR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "ÎιαÏÏΜΎεÏη ÎÏÎ±ÎŒÎŒÎ®Ï ÎΜÏολÏΜ" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s ÎήÏειÏ:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "΀αÏÏÏηÏα:" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "ÎÎγεΞοÏ:" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "ÎλοκλήÏÏÏη Ïε: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "αΜαΌοΜή: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "ÎαÏάÏÏαÏη:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "Ïε ÏαÏÏη" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "εκÏελείÏαι" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "ÏÏ
Μολική ÏαÏÏÏηÏα" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "ÎÏÏεία ÏÏηΜ οÏ
Ïά" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "ΣÏΜολο" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr " ÎεΜοÏ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Î ÏοÏΞήκη ΣÏ
ΜΎÎÏÎŒÏΜ" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " ÎιαÏείÏιÏη ÎÏ
ÏάÏ" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " ÎιαÏείÏιÏη ΣÏ
λλÎκÏη " + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " ÎΜεÏγοÏοίηÏη/ÎÎŽÏαΜοÏοίηÏη" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " ΀εÏΌαÏιÏÎŒÏÏ ÎιακοΌιÏÏή" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " ÎΟοΎοÏ" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "ΧÏήÏη Όε: add <Package name> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "ÎλεγÏÎ¿Ï %d ÏÏ
ΜΎÎÏÎŒÏΜ:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "΀ο αÏÏείο ΎεΜ Ï
ÏάÏÏει." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "΀ο pyLoad ÏεÏΌαÏίÏÏηκε" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "ÎÎŒÏαΜίζει ÏηΜ καÏάÏÏαÏη ÏοÏ
ΎιακοΌιÏÏή" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "ÎÎŒÏαΜίζει ÏÎ¹Ï Î»Î®ÏÎµÎ¹Ï Ïε οÏ
Ïά" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "ÎÎŒÏαΜίζει ÏÎ¹Ï Î»Î®ÏÎµÎ¹Ï ÏÏο ÏÏ
λλÎκÏη" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Î ÏοÏΞÎÏει Ïο ÏακÎÏο ÏÏηΜ οÏ
Ïά" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Î ÏοÏΞÎÏει Ïο ÏακÎÏο ÏÏο ÏÏ
λλÎκÏη" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "ÎιαγÏαÏή αÏÏείοÏ
αÏÏ ÎÏ
Ïά/ΣÏ
λλεκÏη" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "ÎιαγÏαÏή ÏακÎÏÏΜ αÏÏ ÎÏ
Ïά/ΣÏ
λλÎκÏη" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "ÎεÏακίΜηÏη ÏακÎÏÏΜ αÏÏ ÏηΜ ÎÏ
Ïά ÏÏο ΣÏ
λλÎκÏη και αΜÏίÏÏÏοÏα" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "ÎÏαΜεκκίΜηÏη αÏÏείÏΜ" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "ÎÏαΜεκκίΜηÏη ÏακÎÏÏΜ" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "ÎλεγÏÎ¿Ï ÎºÎ±ÏάÏÏαÏÎ·Ï ÏÏΜΎεÏηÏ. ÎειÏοÏ
Ïγεί Όε ÏοÏικά container" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "ÎλεγÏÎ¿Ï ÎºÎ±ÏάÏÏαÏÎ·Ï ÏÏΜΎεÏÎ·Ï ÎµÎœÏÏ Î±ÏÏείοÏ
container" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "ΠαÏÏη ÏοÏ
ΎιακοΌιÏÏή" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "ÏÏ
ΜÎÏιÏη λήÏεÏΜ" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "ÎΜαλλαγή ÏαÏÏηÏ/εκÏÎλεÏηÏ" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "ÏεÏΌαÏιÏÎŒÏÏ ÎŽÎ¹Î±ÎºÎ¿ÎŒÎ¹ÏÏή" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "ÎίÏÏα εΜÏολÏΜ:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "ÎÎŽÏ
ΜαΌία εγγÏαÏÎ®Ï ÏοÏ
αÏÏείοÏ
ÏÏ
ΞΌίÏεÏΜ ÏοÏ
ÏÏήÏÏη" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "ÎÏαιÏείÏαι Ïο py-openssl για ÏÏΜΎεÏη Ïε αÏ
ÏÏΜ Ïο pyLoad Core." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "ÎιεÏΞÏ
ΜÏη:" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "ÎÏÏα:" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "ÎΜοΌα ÏÏήÏÏη:" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "ÎÏΎικÏÏ ÏÏήÏÏη:" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "΀α ÏÏοιÏεία ÏÏΜΎεÏÎ·Ï ÎµÎ¯ÎœÎ±Î¹ λάΞοÏ." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "ÎÎŽÏ
ΜαΌία ÏÏΜΎεÏÎ·Ï ÏÏη ΎιεÏΞÏ
ΜÏη %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "ÎÏαιÏείÏαι Ïο py-openssl για ÏÏΜΎεÏη Ïε αÏ
ÏÏΜ ÏοΜ pyLoad Core." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "H αλληλεÏιΎÏαÏÏική λειÏοÏ
Ïγία αγΜοήΞηκε εÏÏÏοΜ ÎŽÏÏαÏε κάÏÎ¿Î¹ÎµÏ ÎµÎœÏολÎÏ." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Î ÏοÏΞήκη ΠακÎÏοÏ
:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "ÎιÏάγεÏε ÏΜοΌα για Ïο καιΜοÏÏγιο ÏακÎÏο" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "ΠακÎÏο: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "ÎΜάλÏ
Ïη ÏÏΜ ÏÏ
ΜΎÎÏÎŒÏΜ ÏοÏ
ΞÎλεÏε Μα ÏÏοÏΞÎÏεÏε. " + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "ΠληκÏÏολογείÏÏε %s ÏÏαΜ ÏελειÏÏεÏε. " + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "ΣÏΜΎεÏΌοι ÏοÏ
ÏÏοÏÏÎΞηκαΜ:" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "εÏιÏÏÏοÏή ÏÏο αÏÏÎ¹ÎºÏ ÎŒÎµÎœÎ¿Ï" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "ÎιαÏείÏιÏη ÏακÎÏÏΜ:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "ÎιαÏείÏιÏη ΣÏ
ΜΎÎÏÎŒÏΜ:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "΀ι ΞÎλεÏε Μα ΌεÏακιΜήÏεÏε;" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "΀ί ΞÎλεÏε Μα ΎιαγÏάÏεÏε;" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "΀ί ΞÎλεÏε Μα εÏαΜεκκιΜήÏεÏε;" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "ÎÏιλÎΟÏε εΜÎÏγεια ή ÏληκÏÏολογήÏÏε αÏÎ¹ÎžÎŒÏ ÏακÎÏοÏ
." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "ΎιαγÏαÏή" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "ΌεÏακίΜηÏη" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "εÏαΜεκκίΜηÏη" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - ÏÏοηγοÏΌεΜο" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - εÏÏΌεΜο" + diff --git a/locale/el/LC_MESSAGES/setup.po b/locale/el/LC_MESSAGES/setup.po new file mode 100644 index 000000000..0f9903201 --- /dev/null +++ b/locale/el/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Greek\n" +"Language: el_GR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "ÎαλÏÏ Î®Î»ÎžÎ±Ïε ÏÏο ÎÎ¿Î·ÎžÏ Î¡ÏΞΌιÏÎ·Ï ÏοÏ
pyLoad" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Îα γίΜει ÎλεγÏÎ¿Ï ÎºÎ±Î¹ βαÏική ÏÏΞΌιÏη ÏοÏ
ÏÏ
ÏÏήΌαÏÏÏ ÏαÏ, ÏÏÏε Μα εκÏελεÏÏεί Ïο pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "Î ÏιΌή ÏÏÎ¹Ï Î±Î³ÎºÏÎ»ÎµÏ [] είΜαι ÏάΜÏα η ÏÏοεÏιλεγΌÎΜη ÏιΌή," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "Ïε ÏεÏίÏÏÏÏη ÏοÏ
ΎεΜ εÏιΞÏ
ΌείÏε αλλαγή ή αΌÏιβάλλεÏε για ÏηΜ εÏιλογή ÏαÏ, αÏλά ÏαÏήÏÏε enter. " + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "ÎηΜ ΟεÏΜάÏε: ÎÏοÏείÏε ÏάΜÏα Μα εκÏελÎÏεÏε ΟαΜά ÏοΜ ÎοηΞÏ, ειÏάγοΜÏÎ±Ï Ïη ÏαÏάΌεÏÏο --setup ή -s, καÏά ÏηΜ εκÏÎλεÏη ÏοÏ
pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "ÎΜ αΜÏιΌεÏÏÏίÏεÏε ÏÏοβλήΌαÏα Όε Ïο ÎοηΞÏ, ÏαÏήÏÏε CTRL-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "για Μα εγκαÏαλείÏεÏε και Μα αÏοÏÏÎÏεÏε ÏηΜ αÏ
ÏÏΌαÏη εκÏÎλεÏή ÏοÏ
." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "ÎÏαΜ είÏÏε ÎÏÎ¿Î¹ÎŒÎ¿Ï Î³Î¹Î± ÏοΜ ÎλεγÏο ÏοÏ
ÏÏ
ÏÏήΌαÏοÏ, ÏαÏήÏÏε enter." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "ÎÏαιÏοÏΜÏαι Ïα pycurl, sqlite και python 2.5, 2.6 ή 2.7 για Μα εκÏελÎÏεÏε Ïο pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "ΠαÏÎ±ÎºÎ±Î»Ï ÎºÎ¬ÎœÎµÏε ÏÎ¹Ï ÎŽÎ¹Î¿ÏΞÏÏÎµÎ¹Ï ÎºÎ±Î¹ εκÏελÎÏÏε ΟαΜά Ïο pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "ΠεγκαÏάÏÏαÏη Ξα ÏεÏΌαÏιÏÏεί." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Î ÎλεγÏÎ¿Ï ÏοÏ
ÏÏ
ÏÏήΌαÏÎ¿Ï Î¿Î»Î¿ÎºÎ»Î·ÏÏΞηκε, ÏαÏήÏÏε Ïο enter για Μα ΎείÏε Ïα αÏοÏελÎÏΌαÏα." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## ÎαÏάÏÏαÏη ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "αÏοκÏÏ
ÏÏογÏάÏηÏη ÏεÏιεÏÏΌεΜοÏ
" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "ÏÏΜΎεÏη ssl" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "αÏ
ÏÏΌαÏη αÏοκÏÏ
ÏÏογÏάÏηÏη captcha" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "ÎιεÏαÏή ιÏÏοÏ" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "ΧαÏακÏηÏιÏÏικά ΎιαΞÎÏιΌα:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "ΧαÏακÏηÏιÏÏικά ÏοÏ
λείÏοÏ
Μ:" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "ΎεΜ είΜαι ΎιαΞÎÏιΌο Ïο py-crypto" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "ÎÏ
ÏÏ Î±ÏαιÏείÏαι αΜ ΞÎλεÏε Μα αÏοκÏÏ
ÏÏογÏαÏήÏεÏε αÏÏεία container." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "ΎεΜ είΜαι ΎιαΞÎÏιΌο Ïο SSL" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "ÎÏ
ÏÏ Î±ÏαιÏείÏαι για ÏηΜ ÏÏαγΌαÏοÏοίηÏη αÏÏÎ±Î»Î®Ï ÏÏΜΎεÏÎ·Ï ÎŒÎµ ÏοΜ ÏÏ
ÏήΜα ή Ïο Webιnterface." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "ÎΜ ΞÎλεÏε Μα ÎÏεÏε ÏÏÏÏβαÏη ÎŒÏΜο ÏοÏικά ÏÏο pyLoad, Ïο ssl ΎεΜ είΜαι ÏÏήÏιΌο." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "ΎεΜ Ï
ÏάÏÏει ΎιαΞÎÏιΌη αΜαγΜÏÏιÏη Captcha" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "ΧÏειάζεÏαι ÎŒÏΜο αÏÏ ÎŒÎµÏικοÏÏ ÎŽÎ¹Î±ÎºÎ¿ÎŒÎ¹ÏÏÎÏ ÎŽÎ¹Î±ÎŒÎ¿Î¹ÏαÏÎŒÎ¿Ï Î±ÏÏείÏΜ και ÏαΜ ÎŽÏÏεάΜ ÏÏήÏÏηÏ." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "΀ο GUI ΎεΜ είΜαι ΎιαΞÎÏιΌο" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "΀ο ÎÏαÏÎ¹ÎºÏ Î ÎµÏιβάλλοΜ ΧÏήÏÏη." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "ΎεΜ βÏÎΞηκε ΌηÏαΜή JavaScript" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Îα Ïο ÏÏειαÏÏείÏε για ΌεÏικοÏÏ ÏÏ
ΜΎÎÏΌοÏ
Ï Click'N'Load. ÎγκαÏαÏÏήÏÏε Spidermonkey, ossp-js, pyv8 ή rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "ÎΜ ΞÎλεÏε ÎŒÏοÏείÏε Μα ακÏ
ÏÏÏεÏε ÏηΜ εγκαÏάÏÏαÏη ÏÏÏα και Μα ΎιοÏΞÏÏεÏε κάÏÎ¿Î¹ÎµÏ ÎµÎŸÎ±ÏÏήÏειÏ." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "ΣÏ
ΜÎÏιÏη Όε ÏηΜ εγκαÏάÏÏαÏη;" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "ÎÎλεÏε Μα αλλάΟεÏε Ïη ΎιαΎÏοΌή ÏοÏ
αÏÏείοÏ
αÏοΞήκεÏ
ÏÎ·Ï ÏÏΜ ÏÏ
ΞΌίÏεÏΜ; Î ÏÏÎÏοÏ
Ïα είΜαι %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "ÎΜ ÏÏηÏιΌοÏοιήÏε Ïο pyLoad Ïε εΟÏ
ÏηÏεÏηÏή ή Ïο ΎιαΌÎÏιÏΌα home βÏίÏκεÏαι Ïε εÏÏÏεÏική ΌΜήΌη flash, Ξα ήÏαΜ καλή ιΎÎα Μα Ïο αλλάΟεÏε." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Îλλαγή ΎιαΎÏÎ¿ÎŒÎ®Ï Î±ÏοΞήκεÏ
ÏÎ·Ï Î±ÏÏείοÏ
ÏÏ
ΞΌίÏεÏΜ;" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "ÎÎλεÏε Μα οÏίÏεÏε ÏÏοιÏεία ÏÏΜΎεÏÎ·Ï ÎºÎ±Î¹ Μα κάΜεÏε ÏÎ¹Ï Î²Î±ÏικÎÏ ÏÏ
ΞΌίÏειÏ;" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "ÎÏ
ÏÏ ÏÏ
ΜιÏÏάÏαι για ÏηΜ ÏÏÏÏη εκÏÎλεÏη." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "ÎηΌιοÏ
Ïγία βαÏÎ¹ÎºÎ®Ï ÏÏΞΌιÏηÏ;" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "ÎÎλεÏε Μα ÏÏ
ΞΌίÏεÏε Ïο SSL;" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "ΡÏΞΌιÏη SSL;" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "ÎÎλεÏε Μα ÏÏ
ΞΌίÏεÏε Ïο ÏεÏιβάλλοΜ Web;" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "ΡÏΞΌιÏη ÏοÏ
Web Interface;" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "ΠεγκαÏάÏÏαÏη ολοκληÏÏΞηκε Όε εÏιÏÏ
Ïία." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "ΠαÏήÏÏε Enter για Μα εΟÎλΞεÏε και Μα εÏαΜεκκιΜήÏεÏε Ïο pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## ÎλεγÏÎ¿Ï Î£Ï
ÏÏήΌαÏÎ¿Ï ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Î ÎκΎοÏη ÏÎ·Ï python ÏοÏ
ÏÏηÏιΌοÏοιείÏε είΜαι ÏÎ¿Î»Ï ÎœÎα, ÏαÏÎ±ÎºÎ±Î»Ï ÏÏηÏιΌοÏοιήÏÏε Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Î ÎκΎοÏη ÏÎ·Ï python ÏοÏ
ÏÏηÏιΌοÏοιείÏε είΜαι ÏÎ¿Î»Ï Ïαλιά, ÏαÏÎ±ÎºÎ±Î»Ï ÏÏηÏιΌοÏοιήÏÏε ÏοÏ
λάÏιÏÏοΜ Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "ÎκΎοÏη Python: ÎÎ" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Î ÎκΎοÏη %s ÏοÏ
jinja2 ÏοÏ
ÎÏεÏε εγκαÏεÏÏηΌÎΜη ÏαίΜεÏαι ÏÎ¿Î»Ï Ïαλιά." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "ÎÏοÏείÏε Μα ÏÏ
ΜεÏίÏÏε, αλλά αΜ ΎεΜ ΎοÏ
λεÏει Ïο Web Interface," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "ÏαÏÎ±ÎºÎ±Î»Ï Î±ÎœÎ±Î²Î±ÎžÎŒÎ¯ÏÏε Ïο ή αÏεγκαÏαÏÏήÏÏε Ïο, Ïο pyLoad ÏÏ
ÎŒÏεÏιλαΌβάΜει Όια εÏαÏκή βιβλιοΞήκη jinja2." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "ÎηÏαΜή JS" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## ÎαÏική ÎγκαÏάÏÏαÏη ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "΀α ακÏλοÏ
Ξα ÏÏοιÏεία ÏÏΜΎεÏÎ·Ï ÎµÎ¯ÎœÎ±Î¹ ÎγκÏ
Ïα για Ïη ÎÏαΌΌή ÎΜÏολÏΜ, Ïο GUI και Ïο ÏεÏιβάλλοΜ Web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "ÎΜοΌα ΧÏήÏÏη" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Îι εΟÏÏεÏικοί ÏελάÏÎµÏ (για Ïο GUI, Ïη ÎÏαΌΌή εΜÏολÏΜ ή άλλο) ÏÏειάζοΜÏαι αÏοΌακÏÏ
ÏÎŒÎΜη ÏÏÏÏβαÏη για Μα λειÏοÏ
ÏγήÏοÏ
Μ ÎŒÎÏÏ ÎŽÎ¹ÎºÏÏοÏ
." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "ÎÎŒÏÏ, αΜ ΞÎλεÏε Μα Μα ÏÏηÏιΌοÏοιήÏεÏε ΌοΜο Ïο Web Interface, ÎŒÏοÏείÏε Μα Ïο αÏεΜεÏγοÏοιήÏεÏε για Μα γλÏ
ÏÏÏεÏε RAM." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "ÎΜεÏγοÏοίηÏη αÏοΌακÏÏ
ÏÎŒÎÎœÎ·Ï ÏÏÏÏβαÏηÏ" + +#: module/setup.py:291 +msgid "Language" +msgstr "ÎλÏÏÏα" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "ÎŠÎ¬ÎºÎµÎ»Î¿Ï ÎŒÎµÏαÏοÏÏÏÏεÏΜ" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "ÎÎγιÏÏÎ¿Ï Î±ÏιΞΌÏÏ ÏαÏ
ÏÏÏÏοΜÏΜ λήÏεÏΜ" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "ΧÏήÏη ÎÏαΜαÏÏΜΎεÏηÏ;" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "΀οÏοΞεÏία αÏÏείοÏ
εΜÏολÏΜ εÏαΜαÏÏΜΎεÏηÏ" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## ÎγκαÏάÏÏαÏη ΠεÏιβάλλοΜÏÎ¿Ï Web ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "ÎΜεÏγοÏοίηÏη ÏεÏιβάλλοΜÏÎ¿Ï Web;" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "ÎιεÏΞÏ
ΜÏη ÏοÏ
Ξα \"ακοÏει\". ÎΜ ÏÏηÏιΌοÏοιήÏεÏε 127.0.0.1 ή localhost, Ïο ÏεÏιβάλλοΜ Web Ξα είΜαι ÏÏοÏβάÏιΌο ÎŒÏΜο ÏοÏικά." + +#: module/setup.py:312 +msgid "Address" +msgstr "ÎιεÏΞÏ
ΜÏη" + +#: module/setup.py:313 +msgid "Port" +msgstr "ÎÏÏα" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "΀ο pyLoad ÏÏοÏÏÎÏει αÏκεÏoÏÏ ÎŽÎ¹Î±ÎºÎ¿ÎŒÎ¹ÏÏÎÏ Ï
ÏοÏÏήÏιΟηÏ. ÎκολοÏ
Ξεί ÏÏΜÏοΌη εÏεΟήγηÏη." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Î ÏοεÏιλεγΌÎÎœÎ¿Ï ÎŽÎ¹Î±ÎºÎ¿ÎŒÎ¹ÏÏήÏ, η καλÏÏεÏη εÏιλογή αΜ ΎεΜ γΜÏÏίζεÏε ÏοιοΜ Μα ΎιαλÎΟεÏε." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "ÎÏ
ÏÏÏ Î¿ ΎιακοΌιÏÏÎ®Ï Ï
ÏοÏÏηÏίζει SSL και είΜαι καλή εΜαλλακÏική λÏÏη Ïε ÏÏÎÏη Όε ÏοΜ ÏÏοεÏιλεγΌÎΜο." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "ÎÏοÏεί Μα ÏÏηÏιΌοÏοιήΞεί αÏÏ ÏοΜ apache και Ïο lighttpd, αÏαιÏείÏαι ÏαÏαΌεÏÏοÏοίηÏη, η οÏοία ΎεΜ είΜαι ÏÎ¿Î»Ï ÎµÏκολη." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Î Î¿Î»Ï Î³ÏήγοÏη εΜαλλακÏική λÏÏη, γÏαΌΌÎΜη Ïε C, αÏαιÏεί libev και γΜÏÏÎµÎ¹Ï linux." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "ÎαÏεβάÏÏε Ïο αÏÏ ÎµÎŽÏ: https://github.com/jonashaag/bjoern, κάΜÏε Ïο compile," + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "και αΜÏιγÏάÏÏε Ïο bjoern.so ÏÏο module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Î ÏοÏοÏή: Σε ÏÏÎ¬ÎœÎ¹ÎµÏ ÏεÏιÏÏÏÏÎµÎ¹Ï Î¿ ÏÏοεÏιλεγΌÎÎœÎ¿Ï ÎŽÎ¹Î±ÎºÎ¿ÎŒÎ¹ÏÏÎ®Ï ÎŽÎµÎœ ΎοÏ
λεÏει. ÎΜ ÏαÏαÏηÏήÏεÏε ÏÏοβλήΌαÏα Όε Ïο Web Interface," + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "εÏιÏÏÏÎÏÏε ÎµÎŽÏ ÎºÎ±Î¹ αλλάΟÏε ÏοΜ Όε ÏοΜ threaded." + +#: module/setup.py:329 +msgid "Server" +msgstr "ÎιακοΌιÏÏήÏ" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## ÎγκαÏάÏÏαÏη SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "ÎκÏελÎÏÏε αÏ
ÏÎÏ ÏÎ¹Ï ÎµÎœÏολÎÏ Î±ÏÏ ÏοΜ Ïάκελο ÏαÏαΌεÏÏοÏοίηÏÎ·Ï ÏοÏ
pyLoad για Μα ΎηΌιοÏ
ÏγήÏεÏε ÏιÏÏοÏοιηÏικά SSL:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "ÎΜ ÏελειÏÏαÏε και Ïλα ÏήγαΜ καλÏÏ, ÏÏÏα ÎŒÏοÏείÏε Μα εΜεÏγοÏοιήÏεÏε Ïο SSL." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "ÎΜεÏγοÏοίηÏη SSL;" + +#: module/setup.py:360 +msgid "Select action" +msgstr "ÎÏιλÎΟÏε εΜÎÏγεια" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - ÎηΌιοÏ
Ïγία/ÎÏεΟεÏγαÏία ÏÏήÏÏη" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - ÎίÏÏα ÏÏηÏÏÏΜ" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - ÎιαγÏαÏή ÏÏήÏÏη" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - ΀εÏΌαÏιÏÎŒÏÏ" + +#: module/setup.py:376 +msgid "Users" +msgstr "ΧÏήÏÏεÏ" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "ÎÏιÏÎŒÏÏ ÎºÎ±Î¹ÎœÎ¿ÏÏÎ¹Î±Ï ÎŽÎ¹Î±ÎŽÏÎ¿ÎŒÎ®Ï ÏÏ
ΞΌίÏεÏΜ, ΎεΜ Ξα ΌεÏαÏεÏΞοÏΜ οι ÏÏÎÏοÏ
ÏÎµÏ ÏÏ
ΞΌίÏειÏ!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "ÎιαΎÏοΌή αÏÏείοÏ
ÏÏ
ΞΌίÏεÏΜ" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "ΠΎιαΎÏοΌή ÏÏ
ΞΌίÏεÏΜ οÏίÏÏηκε, η εγκαÏάÏÏαÏη ÏÏÏα Ξα κλείÏει, ÏαÏÎ±ÎºÎ±Î»Ï ÎºÎ¬ÎœÏε εÏαΜεκκίΜηÏη για Μα ÏÏ
ΜεÏίÏÏε." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "ΠαÏήÏÏε Enter για ÎΟοΎο." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "ΠοÏιÏÎŒÏÏ ÏÎ·Ï ÎŽÎ¹Î±ÎŽÏÎ¿ÎŒÎ®Ï ÏÏ
ΞΌίÏεÏΜ αÏÎÏÏ
Ïε: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: λείÏει" + +#: module/setup.py:464 +msgid "Password: " +msgstr "ÎÏΎικÏÏ ÏÏήÏÏη:" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "ΠκÏΎικÏÏ ÎµÎ¯ÎœÎ±Î¹ ÏÎ¿Î»Ï ÎŒÎ¹ÎºÏÏÏ. ΧÏηÏιΌοÏοιήÏÏε ÏοÏ
λάÏιÏÏοΜ 4 ÏαÏακÏήÏεÏ." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "ÎÏΎικÏÏ (ΟαΜά):" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Îι κÏΎικοί ΎεΜ ÏαιÏιάζοÏ
Μ" + +#: module/setup.py:493 +msgid "yes" +msgstr "Μαι" + +#: module/setup.py:493 +msgid "true" +msgstr "ÏÏÏÏÏ" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "ÏÏι" + +#: module/setup.py:496 +msgid "false" +msgstr "λάΞοÏ" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "ÎαΜΞαÏÎŒÎΜη ειÏαγÏγή" + diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo Binary files differdeleted file mode 100755 index 1767783dd..000000000 --- a/locale/en/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/en/LC_MESSAGES/pyLoad.mo b/locale/en/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100755 index 1767783dd..000000000 --- a/locale/en/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/en/LC_MESSAGES/pyLoadCli.mo b/locale/en/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100755 index 1767783dd..000000000 --- a/locale/en/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/en/LC_MESSAGES/pyLoadGui.mo b/locale/en/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100755 index 1767783dd..000000000 --- a/locale/en/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/en/LC_MESSAGES/setup.mo b/locale/en/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100755 index 1767783dd..000000000 --- a/locale/en/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/eo/LC_MESSAGES/django.po b/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 000000000..3758d96c9 --- /dev/null +++ b/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Esperanto\n" +"Language: eo_UY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/eo/LC_MESSAGES/pyLoad.po b/locale/eo/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..a4012d712 --- /dev/null +++ b/locale/eo/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Esperanto\n" +"Language: eo_UY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/eo/LC_MESSAGES/pyLoadCli.po b/locale/eo/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..d098a93a2 --- /dev/null +++ b/locale/eo/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Esperanto\n" +"Language: eo_UY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/eo/LC_MESSAGES/setup.po b/locale/eo/LC_MESSAGES/setup.po new file mode 100644 index 000000000..259ad8543 --- /dev/null +++ b/locale/eo/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Esperanto\n" +"Language: eo_UY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index 899597735..000000000 --- a/locale/es/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po new file mode 100644 index 000000000..4c928537a --- /dev/null +++ b/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Spanish\n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Solicitud de nuevo Captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Por favor lee el texto en el captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad se reinició" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "apagado" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Ãxito" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "encendido" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "¿Estás seguro de que quieres salir de pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Reiniciar enlace" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Borrar enlace" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Por favor, introduce un nombre de paquete." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Por favor, haz clic en la posición del captcha correcto." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Se produjo un error." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "La carpeta está vacÃa" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Fallidos" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "No hay captchas." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Las contraseñas no coinciden." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Ajustes guardados." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nueva carpeta" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "¿Estás seguro de que quieres reiniciar pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "esperando a %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Descargas activas" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Inicio" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "Cola" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "Recolector" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Descargas" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Registros" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Configuración" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Nombre" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Estado" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Información" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Tamaño" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Progreso" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Iniciar sesión" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Usuario" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Contraseña" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Tu nombre de usuario y contraseña no coinciden. Por favor inténtalo de nuevo." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Para reiniciar tus datos de inicio de sesión o añadir un usuario ejecuta:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Borrar terminados" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Reiniciar Fallidos" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Carpeta:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Contraseña:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Editar paquete" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Editar los detalles del paquete siguiente." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Nombre del paquete." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Carpeta" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Nombre de la subcarpeta para estas descargas." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Lista de contraseñas usadas para unrar." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Enviar" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Reiniciar" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Se ha cerrado sesión correctamente." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Ruta" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absoluta" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativa" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "nombre" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "tamaño" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "tipo" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "última modificación" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "directorio padre" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "sin contenido" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "General" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Complementos" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Cuentas" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Elige una sección del menú" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "Premium" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Válido hasta" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Tráfico restante" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Tiempo" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Máx. en Paralelo" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "¿Borrar?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "válido" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "inválido" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "sÃ" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "no" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Añadir" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Agregar cuenta" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Introduce los datos de tu cuenta para usar caracterÃsticas premium." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Tu nombre de usuario." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "La contraseña para esta cuenta." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Tipo" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Elige el proveedor de alojamiento para tu cuenta." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Iniciar" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "anterior" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "siguiente" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Fin" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Novedades" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Soporte" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Sistema" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "Python:" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "S.O.:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "versión de pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Carpeta de instalación:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Carpeta de configuración:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Carpeta de descarga:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Espacio Libre:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Idioma:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Puerto de interfaz web:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Puerto de interfaz remota:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Configuración" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Administrador de archivos" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Añadir paquete" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Pega tus enlaces o carga un archivo contenedor." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Nombre del nuevo paquete." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Enlaces" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Pega tus enlaces o cualquier texto aquà y pulsa el botón filtrar." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtrar urls" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Contraseña para el archivo-RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Archivo" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Cargar contenedor." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Destino" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Leyendo captcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "Captcha" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "El captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Texto" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Introduzca el texto en el captcha." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Cerrar" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Interfaz web" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "¡Actualización de pyLoad disponible!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins actualizados, ¡por favor reinicia!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Esperando captcha" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Salir" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrar" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Información" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "¡Por favor, inicie sesión!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Parar" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Cancelar" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Descarga:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Reconectar:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Velocidad:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Activo:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Recargar" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "cargando" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Volver al principio" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Salir de pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Reiniciar pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Para añadir un usuario o cambiar contraseñas usa:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Importante: ¡El usuario Admin tiene siempre todos los permisos!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Cambiar Contraseña" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "Admin" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Permisos" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "cambiar" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Introduce tu contraseña actual y la deseada." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Usuario" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Contraseña actual" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nueva contraseña" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "La nueva contraseña." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nueva contraseña (repetir)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Por favor, repite la nueva contraseña." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "No tienes permiso para acceder a esta página." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "No se encuentra el directorio de descarga." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ilimitado" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "no disponible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Ejecuta pyload.py -s para acceder a la instalación." + diff --git a/locale/es/LC_MESSAGES/pyLoad.mo b/locale/es/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 90aa70f1d..000000000 --- a/locale/es/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/es/LC_MESSAGES/pyLoad.po b/locale/es/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..6f94da4ff --- /dev/null +++ b/locale/es/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Spanish\n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Señal de salida recibida" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad ya está ejecutándose con pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Cambio de grupo fallido: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Cambio de usuario fallido: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "carpeta para los registros" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Iniciando" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Usando directorio de inicio: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto va a decodificar archivos contenedores" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "carpeta para archivos temporales" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "carpeta de descargas" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL para conexión segura" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Moviendo la configuración antigua de usuario a la BD" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Por favor, comprueba tus datos de inicio de sesión con ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Se han eliminado todos los enlaces" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Tiempo de descarga: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Espacio libre: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Activando Cuentas..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Activando Plugins..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad está funcionando" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "reiniciando pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad se cierra" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Instalar %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "no se pudo encontrar %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "no se pudo crear %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "apagando..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "ha ocurrido un error mientras se apagaba" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyload terminado desde el Terminal" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "El archivo de la base de datos fue eliminado por ser de una versión incompatible." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "El archivo de la base de datos NO pudo convertirse." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "La base de datos se convirtió de la v2 a la v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "La base de datos se convirtió de la v3 a la v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Convirtiendo la BD Django antigua" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "Terminado" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "sin conexión" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "en lÃnea" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "en cola" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "omitido" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "esperando" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "temp. sin conexión" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "comenzando" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "fallido" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "abortado" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "descifrando" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "personalizado" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "descargando" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "procesando" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "desconocido" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paquete terminado: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "Usando SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Error de backend remoto: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Iniciando %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Fallo al cargar servidor %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "esperando a %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "Certificados SSL no encontrados." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Lo sentimos, ya no admitimos iniciar %s directamente en pyLoad" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Puedes utilizar el servidor con hilos que ofrece un buen rendimiento y ssl," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "por supuesto puedes usar aún tu %s existente con el servidor fastcgi de pyLoad" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "las configuraciones de ejemplo se encuentran en el directorio module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "¡No puedes usar %(server)s, python-flup no está instalado!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Error importando servidor ligero: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "Debes descargar y compilar bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Copia el módulo boern.so a la carpeta module/lib o usa la instalación setup.py" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Por supuesto debes estar familiarizado con linux y saber cómo compilar software" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Servidor en modo threaded, debido a problemas de rendimiento en Windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Este servidor no ofrece SSL, considera el usar el servidor con hilos en su lugar" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Iniciando servidor web incorporado: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Iniciando servidor web SSL con hilos : %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Iniciando servidor web con hilos: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Iniciando servidor fastcgi: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Iniciando servidor web ligero (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "No tienes permiso para acceder a esta página." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "No se encuentra el directorio de descarga." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ilimitado" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "no disponible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Ejecuta pyload.py -s para acceder a la instalación." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Descarga por trozos fallida, recurro a una única conexión | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Iniciando descarga: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Descarga finalizada: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Plugin %s no encuentra una función." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Descarga abortada: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Descarga reiniciada: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Descarga está fuera de servicio: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "La descarga está temporalmente fuera de servicio: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Descarga fallida: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "No pude conectar al servidor o conexión reiniciada, esperando 1 minuto y reintentando." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Descarga omitida: %(name)s debido a %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Descifrado comienza en: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Descifrado fallido: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Reintentando %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Obtención de información para %(name)s fallida | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Error ejecutando enlaces: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Falló la activación de %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Plugins activos: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Plugins desactivados: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Reconexión Fallida: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "¡Script de reconexión no encontrado!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Iniciando reconexión" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "¡Fallo al ejecutar script de reconexión!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Reconectado, nueva dirección IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "No hay suficiente espacio libre en el dispositivo" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "No pude iniciar sesión con cuenta %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Contraseña Incorrecta" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "La hora %s tiene un formato incorrecto, use: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "La cuenta %s no tiene tráfico suficiente, se comprobará otra vez en 30min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "La cuenta %s ha expirado, comprobando de nuevo en 1 hora" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "Limite de descargas alcanzado" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s tiene un patrón inválido." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Error importando %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "No se cargó ningún proveedor" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Activa descarga directa en tu cuenta de Bitshare" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "LinkList no puede ser limpiado." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Ajustes de cuenta eliminados, debido al nuevo formato de la configuración." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Autorización requerida (usuario:contraseña)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Por favor, introduce tu cuenta de %s o desactiva este plugin" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "HabÃa Código HTML en el archivo Descargado (%s)... ¿error de redireccionamiento? La Descarga se reiniciará." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Archivo no disponible temporalmente" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: esperando entre descargas %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: esperando captcha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "El archivo descargado estaba vacÃo" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "Clave de API inválida" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: No hay suficiente tráfico" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Tráfico excedido" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Tráfico compartido (descarga directa)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Ya estás descargando desde esta dirección IP, esperando 60 segundos" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Código de autenticación inválido, la descarga se reiniciará" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: No quedan espacios disponibles" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Necesitas una cuenta premium para este archivo" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Nombre de archivo inválido" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Error con descargas en paralelo, esperando 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "No has iniciado sesión." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Error de descifrado" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "No se proporcionó archivo de clave en la URL" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Código de error:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "El archivo no existe." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Los plugins se han actualizado, por favor reinicie pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Plugins actualizados y cargados de nuevo" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "No hay disponibles actualizaciones de plugins" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "No hay actualizaciones de pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Nueva versión %s de pyLoad disponible ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Descarguela aquÃ: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "No se puede conectar con el servidor para actualizar" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nueva versión de %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Error mientras se actualizaba %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "No coincide la versión" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Descarga finalizada: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nueva Petición de Captcha: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Conteste con 'c %s texto al captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "Por favor, añada primero su cuenta premium.to y reinicie pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Añadido %s desde HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "%s no instalado" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "No se puede activar %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Activado" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "No se ha activado ningún plugin de extracción" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Paquete %s encolado para su posterior extracción" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Comprobar paquete %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Extraer a %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "No se encontraron archivos para extraer" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "extrayendo" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Protegido con contraseña" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Contraseña errónea" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Borrando archivos %s" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Extracción finalizada" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Error de Archivo" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "El CRC no coincide" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Error Desconocido" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Error de configuración de usuario y grupo" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: Puerto 9666 ya está en uso" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s créditos restantes" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "No se ha podido enviar la respuesta." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Su cuenta de CaptchaTrader no tiene créditos suficientes" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "No se ha encontrado lista de cifradores" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "La lista de cifradores está vacÃa" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Descarga finalizada: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Nuevo CaptchaID desde carga: %s: %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Su Cuenta Captcha 9kw.eu no tiene suficientes créditos" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Código instalado para %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Código no ejecutable:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Error en %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Su cuenta de ExpertDecoders no suficientes créditos" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Por favor, añada primero su cuenta rehost.to y reinicie pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "Por favor, agrega primero una cuenta válida de premiumize.me y reinicia pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d créditos restantes" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil y tesseract no están instalados y no hay cliente conectado para descifrar captcha" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "No se obtuvieron resultados para el captcha en el tiempo asignado de ninguno de los plugins." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Configuración de usuario y grupo fallida: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "No hay cliente conectado para descifrar el captcha" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Paquete %(name)s agregado que contiene %(count)d enlaces" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Agregados %(count)d enlaces al paquete #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "No se detectó ningún motor de js, por favor instale Spidermonkey, ossp-js, pyv8 o rhino" + diff --git a/locale/es/LC_MESSAGES/pyLoadCli.mo b/locale/es/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index f969ad0d1..000000000 --- a/locale/es/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/es/LC_MESSAGES/pyLoadCli.po b/locale/es/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..1e9fc0af6 --- /dev/null +++ b/locale/es/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Spanish\n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Interfaz de LÃnea de Comandos" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s Descargas:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Velocidad: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Tamaño: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Finalizado el: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "esperando: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Estado:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "pausado" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "ejecutando" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "Velocidad total" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Ficheros en cola" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Total" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Menú:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Añadir enlaces" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Administrar Cola" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " Administrar Recolector" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " Detener/Reanudar Servidor" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Parar servidor" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Salir" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Por favor usa esta sintaxis: add <Package name> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Comprobando %d enlace(s):" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "El archivo no existe." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad ha finalizado" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Muestra el estado del servidor" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Muestra las descargas en cola" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Muestra las descargas en recolector" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Agregar paquetes a la cola" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Agrega un paquete al recolector" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Borrar Archivos de la Cola/Recolector" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Borrar Paquetes de la Cola/Recolector" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Mover Paquetes de la Cola al Recolector o viceversa" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Reiniciar archivos" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Reiniciar paquetes" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Comprobar el estado en-linea, trabaja con el contenedor local" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Comprueba el estado en-linea de un contenedor" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Pausar el servidor" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "continuar descargas" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Alternar detener/reanudar" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "parar servidor" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Lista de comandos:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "No se puede escribir el archivo de configuración del usuario" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Necesitas py-openssl para conectar a este Núcleo pyLoad." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Dirección: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Puerto: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Usuario: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Contraseña: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Los datos de inicio de sesión son incorrectos." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "No se puede establecer la conexión a %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Necesitas py-openssl para conectar a este núcleo pyLoad." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Modo interactivo ignorado ya que pasaste algunas órdenes." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Agregar Paquete:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Introduce un nombre para el paquete nuevo" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Paquete: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Analizar los enlaces que quieres añadir." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Teclea %s cuando acabes." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Enlaces añadidos: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " volver al menú principal" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Administrar Paquetes:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Administrar Enlaces:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "¿Qué quieres mover?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "¿Qué quieres borrar?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "¿Qué quieres reiniciar?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Elige lo que quieres hacer o introduce el número de paquete." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "borrar" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "mover" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "reiniciar" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - anterior" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - siguiente" + diff --git a/locale/es/LC_MESSAGES/pyLoadGui.mo b/locale/es/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index a4944783f..000000000 --- a/locale/es/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/es/LC_MESSAGES/setup.mo b/locale/es/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index 87c4dd811..000000000 --- a/locale/es/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/es/LC_MESSAGES/setup.po b/locale/es/LC_MESSAGES/setup.po new file mode 100644 index 000000000..9595559bb --- /dev/null +++ b/locale/es/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Spanish\n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "s" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Bienvenido al Asistente de Configuración de pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Se revisará tu sistema y se hará una configuración básica para ejecutar pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "El valor entre corchetes [] siempre es el valor por defecto," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "en caso que no quieras cambiarlo o no estés seguro de que opción elegir, solo presiona entrar." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "No lo olvides: siempre puedes volver a ejecutar este asistente con el parámetro --setup ó -s, cuando inicies pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Si tienes algún problema con el asistente presiona Ctrl-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "para abortar y no permitirle volver a iniciarse automáticamente con pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Cuando estés listo para la revisión del sistema, presiona entrar." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Necesitas pycurl, sqlite y python 2.5, 2.6 ó 2.7 para ejecutar pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Por favor corrige esto y vuelve a ejecutar pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "El asistente de la instalación se cerrará." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "La revisión del sistema ha finalizado, presiona entrar para ver el informe de estado." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Estado ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "descifrando contenedor" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "conexión SSL" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "descifrado automático de captcha" + +#: module/setup.py:104 +msgid "GUI" +msgstr "GUI" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Interfaz web" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "extensión Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "CaracterÃsticas disponibles:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "CaracterÃsticas no disponibles: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto no disponible" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Necesario si quieres descifrar archivos contenedores." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL no disponible" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Esto es necesario si quieres establecer una conexión segura con el núcleo o la interfaz web." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "SSL no es útil si solamente quieres acceder a pyLoad localmente." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "reconocimiento de captcha no disponible" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Solo necesario para algunos servidores y como usuario gratuito." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "GUI no disponible" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "El Interfaz de Usuario Gráfica." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "motor de JavaScript no encontrado" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Necesario para algunos enlaces Click'N'Load. Instala Spidermonkey, ossp-js, pyv8 o rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Puedes cancelar el asistente ahora y corregir algunas dependencias si quieres." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "¿Desea continuar con el asistente?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "¿Quiere cambiar la ruta de configuración? Actualmente es %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Si usas pyLoad en un servidor o la partición primaria reside en una memoria flash interna, puede ser buena idea cambiarla." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "¿Cambiar la ruta de configuración?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "¿Quiere configurar los datos de acceso y la configuración básica?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Esto se recomienda en la primera ejecución." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "¿Realizar la configuración básica?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "¿Quiere configurar SSL?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "¿Configurar SSL?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "¿Quiere configurar la interfaz web?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "¿Configurar la interfaz web?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Configuración finalizada con éxito." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Pulse entrar para salir y reiniciar pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Revisión del sistema ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Tu versión de python es demasiado nueva, por favor usa Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Tu versión de python es demasiado antigua, por favor usa al menos Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Versión de Python: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Tu versión %s jinja2 instalada parece demasiado antigua." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Puedes continuar de manera segura aunque la interfaz web no funciona," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "por favor actualÃcela o desinstálela, pyLoad incluye una biblioteca jinja2 suficiente." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "Motor JS" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Configuración básica ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Los siguientes datos de acceso son válidos para CLI, GUI e interfaz web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Usuario" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Los clientes externos (GUI, CLI u otros) necesitan acceso remoto para trabajar a través de la red." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "No obstante, si sólo quieres utilizar interfaz web puedes deshabilitarlo para ahorrar ram." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Activar acceso remoto" + +#: module/setup.py:291 +msgid "Language" +msgstr "Idioma" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Directorio de descargas" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Máximas descargas paralelas" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "¿Usar reconectar?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Ubicación del script de reconexión" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Configuración de la Interfaz Web ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "¿Activar interfaz web?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Dirección de escucha, si usas 127.0.0.1 o localhost, la interfaz web solo podrá ser accesible localmente." + +#: module/setup.py:312 +msgid "Address" +msgstr "Dirección" + +#: module/setup.py:313 +msgid "Port" +msgstr "Puerto" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "lapyLoad ofrece varios backends de servidor después de una breve explicación." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Servidor por defecto, la mejor opción si no sabes cual elegir." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Este servidor ofrece SSL y es una buena alternativa al integrado." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Puede ser usado por apache, lighttpd, requiere que lo configures, lo cual no es una tarea fácil." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Una alternativa muy rápida escrita en C, requiere libev y conocimientos de linux." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Obtenlo de aquÃ: https://github.com/jonashaag/bjoern, compÃlalo" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "y copia bjoern.so a module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Atención: En algunos casos raros el servidor integrado no funciona, si notas problemas con la interfaz web" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "vuelve aquà y cambia el servidor integrado por el servidor con hilos." + +#: module/setup.py:329 +msgid "Server" +msgstr "Servidor" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Configuración de SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Ejecuta estos comandos desde la carpeta de configuración pyLoad para crear los certificados ssl:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Si has terminado y todo acabo bien, podrás activar ssl ahora." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "¿Activar SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Elige una acción" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Crear/Editar usuario" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Listado de usuarios" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Eliminar usuario" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Salir" + +#: module/setup.py:376 +msgid "Users" +msgstr "Usuarios" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Configurando nuevo directorio de configuración, ¡la configuración actual no sera transferida!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Directorio de configuración" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Directorio de configuración cambiado, la instalación se cerrara, por favor reinicia para continuar." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Presiona Entrar para salir." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Ajuste del directorio de configuración fallido: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "%s: OK" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: perdido" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Contraseña: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "La contraseña es demasiado corta. Use al menos 4 sÃmbolos." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Contraseña (de nuevo): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Las contraseñas no coinciden." + +#: module/setup.py:493 +msgid "yes" +msgstr "sÃ" + +#: module/setup.py:493 +msgid "true" +msgstr "verdadero" + +#: module/setup.py:493 +msgid "t" +msgstr "v" + +#: module/setup.py:496 +msgid "no" +msgstr "no" + +#: module/setup.py:496 +msgid "false" +msgstr "falso" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Entrada no válida" + diff --git a/locale/fa/LC_MESSAGES/django.po b/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 000000000..d53772faa --- /dev/null +++ b/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Persian\n" +"Language: fa_IR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/fa/LC_MESSAGES/pyLoad.po b/locale/fa/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..c2455afea --- /dev/null +++ b/locale/fa/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Persian\n" +"Language: fa_IR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/fa/LC_MESSAGES/pyLoadCli.po b/locale/fa/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..279daef1b --- /dev/null +++ b/locale/fa/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Persian\n" +"Language: fa_IR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " سرعت: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " ØØ¬Ù
: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ØŽÙØ§Ø³Ù: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "ÙØ¶Ø¹Ûت:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "در ØØ§Ù اجرا" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "سرعت Ú©Ù" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "ÙØ§ÛÙâÙØ§Û درÙ٠صÙ" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Ù
جÙ
ÙØ¹" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Ù
ÙÙ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " اضاÙ٠کرد٠ÙÛÙÚ©" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " ØšØ³ØªÙ Ø³Ø±ÙØ±" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Ø®Ø±ÙØ¬" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "ÙØ§ÛÙ ÙØ¬Ùد ÙØ¯Ø§Ø±Ø¯." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "ØšØ³ØªÙ Ø³Ø±ÙØ±" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "ÙÛØ³Øª Ø¯Ø³ØªÙØ±Ø§Øª:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "ÙØ§ÛÙ ÙŸÛÚ©Ø±ØšÙØ¯Û کارؚر ÙÙ
ÛâØªÙØ§Ùد ÙÙØŽØªÙ ØŽÙØ¯" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "آدرس: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "درگاÙ: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "ÙØ§Ù
کارؚرÛ: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "رÙ
ز Ø¹ØšÙØ±: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Ø§Ø·ÙØ§Ø¹Ø§Øª ÙØ±Ùد ا؎تؚا٠است." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "ØšØ±Ø§Û Ø§ØªØµØ§Ù ØšÙ ÙØ³ØªÙâÛ pyLoad ØšÙ py-openssl ÙÛØ§Ø² Ø¯Ø§Ø±ÛØ¯." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "ÙÛÙÚ©âÙØ§Û اضاÙ٠؎دÙ: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "ØØ°Ù" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "Ø§ÙØªÙاÙ" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "راÙâØ§ÙØ¯Ø§Ø²Û Ù
جدد" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - ÙØšÙÛ" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - ؚعدÛ" + diff --git a/locale/fa/LC_MESSAGES/setup.po b/locale/fa/LC_MESSAGES/setup.po new file mode 100644 index 000000000..2a1c9ad75 --- /dev/null +++ b/locale/fa/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Persian\n" +"Language: fa_IR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "رÙ
ز Ø¹ØšÙØ±: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/fi/LC_MESSAGES/django.po b/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 000000000..04089267b --- /dev/null +++ b/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Finnish\n" +"Language: fi_FI\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/fi/LC_MESSAGES/pyLoad.mo b/locale/fi/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 2c20cfbd4..000000000 --- a/locale/fi/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/fi/LC_MESSAGES/pyLoad.po b/locale/fi/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..857d06854 --- /dev/null +++ b/locale/fi/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Finnish\n" +"Language: fi_FI\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/fi/LC_MESSAGES/pyLoadCli.mo b/locale/fi/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 1ae24953f..000000000 --- a/locale/fi/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/fi/LC_MESSAGES/pyLoadCli.po b/locale/fi/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..6b2c3e606 --- /dev/null +++ b/locale/fi/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Finnish\n" +"Language: fi_FI\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "KomentorivikÀyttöliittymÀ" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s lataa:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "Nopeus:" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "Koko:" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "Valmistunut:" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "Tunnus:" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "odotetaan:" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Valikko:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "LisÀÀ linkkejÀ" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Jonon hallinta" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " KerÀÀjÀn hallinta" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Linkkien hallinta" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/fi/LC_MESSAGES/pyLoadGui.mo b/locale/fi/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 1ae24953f..000000000 --- a/locale/fi/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/fi/LC_MESSAGES/setup.po b/locale/fi/LC_MESSAGES/setup.po new file mode 100644 index 000000000..32aba57dd --- /dev/null +++ b/locale/fi/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Finnish\n" +"Language: fi_FI\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index b7b2a3fb5..000000000 --- a/locale/fr/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 000000000..09089992d --- /dev/null +++ b/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: French\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Nouvelle demande de captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Merci de lire le texte du captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "PyLoad redémarré" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "Eteint" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "SuccÚs" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "Allumé" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Ãtes-vous vraiment sûr de vouloir quitter pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Relancer le lien" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Effacer le lien" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Merci d'entrer un nom de package." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Veuillez cliquer sur le cÃŽté droit du captcha." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Une erreur est survenue." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Le dossier est vide" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Ãchoué" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Aucun captcha à lire." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Les mots de passe ne correspondent pas." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "ParamÚtres enregistrés." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nouveau répertoire" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Ãtes-vous sûr de vouloir redémarrer pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "attend %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Téléchargements actifs" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Page principale" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "File d'attente " + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "Paquets" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Téléchargements" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Configuration" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Nom" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Status" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Taille" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Progression" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Identifiant" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Nom utilisateur" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Mot de passe" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Votre nom d'utilisateur et votre mot de passe ne correspondent pas. Veuillez réessayer." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Pour changer votre mot de passe ou ajouter un nouvel utilisateur, exécutez : " + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Supprimer les liens terminés" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Redémarrer les liens échoués" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Dossier :" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Mot de passe :" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Modifier le paquet" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Editer les détails du paquet ci-dessous." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Le nom du paquet." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Dossier" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Nom du sous-dossier pour ces téléchargements." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Liste des mots de passes utilisés pour décompresser." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Valider" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Réinitialiser" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Vous êtes désormais déconnecté." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Chemin" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absolu" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relatif" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "nom" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "taille" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "derniÚre modification" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "dossier parent" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "pas de contenu" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Général" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Comptes" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Sélectionnez une section à partir du menu" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Valide jusqu'au" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Trafic restant" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Temps" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Nombre maximum en parallÚle" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Supprimer ? " + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "valide" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "invalide" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "oui" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "non" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Ajouter" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Ajouter un compte" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Entrez vos informations de compte pour utiliser les fonctionnalités premium." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Votre nom d'utilisateur." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Le mot de passe pour ce compte." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Choisissez l'hébergeur pour ce compte." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Démarrer" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "préc" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "suiv" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Fin" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Nouvelles" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "SystÚme" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "Python :" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "OS :" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "Version de pyLoad :" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Dossier d'Installation :" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Dossier de configuration :" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Dossier de téléchargement :" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Espace libre :" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Langue :" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Port de l'interface web :" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Port de l'interface à distance :" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Configurer" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Gestionnaire de fichiers" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Ajouter un paquet" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Recopiez vos liens ou envoyez un conteneur." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Le nom du nouveau paquet." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Liens" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Collez vos liens ici ou n'importe quel texte, et cliquez sur le bouton « Filtrer les URL »." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtrer les URL" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Mot de passe de l'archive RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Fichier" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Envoyer un conteneur." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Destination" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Lecture du catcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Le captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Texte" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Veuillez taper le texte du captcha." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Fermer" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Interface web" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "Mise à jour de pyLoad disponible !" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins mis à jour, redémarrez !" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha en attente" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Déconnexion" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administration" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Information" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Veuillez vous connecter !" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Arrêter" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Annuler" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Téléchargement :" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Reconnexion :" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Vitesse :" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Actif :" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Recharger la page" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "chargement" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Revenir en haut" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Quitter pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Redémarrer pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Pour ajouter un utilisateur ou modifier un mot de passe, utilisez :" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Important : L'utilisateur Admin a tous les droits !" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Modifier le mot de passe" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "modifier" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Entrez votre mot de passe actuel et celui souhaité." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Utilisateur" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Mot de passe actuel" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Le nouveau mot de passe." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nouveau mot de passe (répéter)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "S'il vous plaît répétez le nouveau mot de passe." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Vous n'avez pas la permission d'accéder à cette page." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Répertoire de téléchargement introuvable." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "Illimité" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "non disponible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Lancez pyload.py -s pour accéder au paramétrage." + diff --git a/locale/fr/LC_MESSAGES/pyLoad.mo b/locale/fr/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 95fd73cae..000000000 --- a/locale/fr/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/fr/LC_MESSAGES/pyLoad.po b/locale/fr/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..cd55bd545 --- /dev/null +++ b/locale/fr/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: French\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Signal d'arrêt reçu" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad est déjà lancé avec le pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Echec lors du changement de groupe: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Echec lors du changement d'utilisateur: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "dossier des logs" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Démarrage" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Utilisation du dossier principal : %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto pour décoder les fichiers conteneurs" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "dossier des fichiers temporaires" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "dossier des téléchargements" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL pour les connexions sécurisées" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Déplacement des anciennes configurations utilisateur vers la BDD" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Vérifiez vos identifiants avec ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Tous les liens ont été supprimés" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Temps de téléchargement : %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Espace libre : %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Activation des comptes ..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Activation des Extensions..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad est opérationnel" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "redémarrage de pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad se termine" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Installation %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "impossible de trouver %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "impossible de créer %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "arrêt..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "erreur lors de l'arrêt" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyLoad a été tué depuis le Terminal" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "La base de données des fichiers est incompatible et a été supprimé." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "La base de données NE peut PAS être convertie." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "La base de données a été convertie de la v2 vers la v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "La base de données a été convertie de la v3 vers la v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Conversion de l'ancienne BDD Django" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "fini" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "hors ligne" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "en ligne" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "en file d'attente" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "ignoré" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "en attente" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "temp. hors ligne" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "démarrage" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "échoué" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "annulé" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "décryptage" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "personnalisé" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "téléchargement en cours" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "traitement en cours" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "inconnu" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paquet terminé : %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "Utilise SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Erreur du backend distant: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Démarre %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Ãchec du chargement du backend %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "attend %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "Certificats SSL non trouvés." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Désolé, nous avons arrêté le support du démarrage de %s directement dans pyLoad" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Vous pouvez utiliser le serveur \"threaded\" qui offre de bonnes performances et le ssl," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "bien sur vous pouvez toujours utiliser vos %s existants avec pyLoads fastcgi server" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "les exemples de configurations sont localisés dans le répertoire module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Ne peut utiliser %(server)s, python-flup n'est pas installé!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Erreur lors de l'importation du serveur léger : %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "Vous devez télécharger et compiler bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Copiez le fichier boern.so dans le dossier module/lib, ou utilisez setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Ãvidemment vous devez être familier avec Linux et savoir comment compiler un logiciel" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Serveur placé en mode âthreadedâ, en raison de problÚmes de performances connus sous Windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Ce serveur ne permet pas la connexion SSL, vous devriez envisager d'utiliser le mode âthreadedâ à la place" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Démarrage serveur web interne: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Démarrage serveur web SSL : %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Démarrage serveur web : %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Démarrage serveur webfastcgi : %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Démarrage du serveur léger (bjoern) : %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Vous n'avez pas la permission d'accéder à cette page." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Répertoire de téléchargement introuvable." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "Illimité" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "non disponible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Lancez pyload.py -s pour accéder au paramétrage." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Téléchargement par blocs échoué, repli vers une seule connexion | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Le téléchargement commence : %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Téléchargement terminé : %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Il manque une fonction au plugin %s." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Abandon du téléchargement : %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Téléchargement redémarré : %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Le téléchargement est hors-ligne : %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Le téléchargement est temporairement hors ligne: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Téléchargement échoué : %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Impossible de se connecter à l'hÃŽte ou connexion perdue, prochain essai dans une minute." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Téléchargement ignoré : %(name)s à cause de %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Démarrage du décryptage : %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Décryptage échoué : %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Nouvelle tentative en cours %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Ãchec de la collecte des infos pour %(name)s | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Erreur de l'exécution du hook : %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Impossible d'activer %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Plugins activés: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Plugins désactivés: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "La reconnexion a échoué : %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Script de reconnexion non trouvé !" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Lancement de la reconnexion" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Echec d'exécution du script de reconnexion !" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Reconnecté, nouvelle IP : %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Il n'y a pas assez de place sur le périphérique" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Impossible de s'identifier avec le compte %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Mauvais mot de passe" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "Votre heure %s utilise un format incorrect, utilisez 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "Le compte %s n'a pas assez de trafic, re-vérification dans 30 minutes" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "Le compte %s a expiré, re-vérification dans 1H" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "Limite de téléchargement atteinte" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s a un format invalide." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Erreur d'importation %(name)s : %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Aucun hébergeur chargé" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Activez le téléchargement direct dans votre compte Bitshare" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "Le fichier links.txt ne peut être vidé." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Paramétrage du compte supprimé, du fait d'un nouveau format de configuration." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Autorisation requise (identifiant:mot de passe)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Veuillez entrer votre compte %s ou désactivez ce plugin" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "Il y avait du code HTML dans le fichier téléchargé (%s)... erreur de redirection ? Le téléchargement va redémarrer." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Fichier temporairement indisponible" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload : attente de %d s entre chaque téléchargements." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload : attendre le captcha pendant %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "Le fichier téléchargé est vide" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "La clé de l'API est invalide" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s : il ne reste pas assez de trafic" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Le trafic a été dépassé" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare : partage du trafic (téléchargement direct)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Un téléchargement est déjà en cours depuis cette adresse, 60 secondes d'attente" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Code d'authentification invalide, le téléchargement va redémarrer" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom : aucun slot disponible" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Vous avez besoin d'un compte premium pour ce fichier" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Le nom du fichier est invalide" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Erreur de téléchargement parallÚle, attente pendant 60 secondes." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Vous n'êtes pas identifiés." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Le déchiffrement à échoué" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "Aucune clé de fichier fournie dans l'URL" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Code d'erreur :" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Le fichier n'existe pas." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Les plugins ont été mis à jour, veuillez redémarrer pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Plugins mis à jour et rechargés" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Aucune mise à jour pour les plugins" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Aucune mise à jour pour pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Nouvelle version %s disponible de pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Téléchargez-le ici : http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Incapable de se connecter au serveur pour les mises à jour" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nouvelle version de %(type)s | %(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Erreur lors de la mise à jour de %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "Les versions discordent" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Téléchargement terminé : %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nouvelle demande de captcha : %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Répondre avec ' le texte c %s sur le captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "Veuillez tout d'abord ajouter votre compte premium.to et redémarrez pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Ajout de %s à partir du HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "%s non installé" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Impossible d'activer %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Activé" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Pas de plugin d'extraction activé" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Le paquet %s est mis dans la file d'attente pour une extraction ultérieure" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Vérification du paquet %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Extraction vers %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Aucun fichier trouvé pour l'extraction" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "extraction en cours" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Mot de passe protégé" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Mot de passe incorrect" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Suppression de %s fichiers" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Extraction terminée" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Erreur d'archive" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC différents" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Erreur inconnue" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "La définition de l'utilisateur et du groupe a échoué" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load : port 9666 déjà en cours d'utilisation" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s crédits restants" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Impossible d'envoyer une réponse." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Votre compte CaptchaTrader n'a pas assez de crédits" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Liste des crypteurs non trouvée" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "La liste des crypteurs est vide" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Téléchargement fini : %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Nouveau CaptchaID de l'upload: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Votre compte de captcha 9kw.eu n'a pas assez de crédits" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Scripts installés pour %s : " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Script non exécutable :" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Erreur dans %(script)s : %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Votre compte ExpertDecoders n'a pas assez de crédits" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Veuillez d'abord ajouter votre compte rehost.to et redémarrez pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "Veuillez d'abord ajouter un compte valide premiumize.me et redémarrez pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d crédits restants" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil et tesseract ne sont pas installés et il n'y a pas de client connecté pour le déchiffrement des captcha" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Pas de résultats pour le captcha obtenu dans le temps impartis par aucun des plugins." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "La définition de l'utilisateur et du groupe a échoué :: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Pas de Client connecté pour le décryptage captcha" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Ajout package %(name)s contenant %(count)d liens" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Ajout de %(count)d liens au paquet #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Aucun moteur JS détecté, s'il vous plaît installez soit SpiderMonkey, ossp-js, pyv8 ou rhino" + diff --git a/locale/fr/LC_MESSAGES/pyLoadCli.mo b/locale/fr/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 460641599..000000000 --- a/locale/fr/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/fr/LC_MESSAGES/pyLoadCli.po b/locale/fr/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..43075a3a1 --- /dev/null +++ b/locale/fr/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: French\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Interface en ligne de commande" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s téléchargement(s) :" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Vitesse : " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Taille : " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Fini dans : " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID : " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "en attente : " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Statut:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "en pause" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "en cours" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "Vitesse totale" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Fichiers en attente" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Menu :" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Ajouter des liens" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "Gérer la file d'attente" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "Gérer le collecteur" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "Mettre en pause/Restaurer le serveur" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Stopper le serveur" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Quitter" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Utilisez cette syntaxe : add <Nom paquet> <lien> <lien2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Vérification de %d liens :" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Le fichier n'existe pas." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad a quitté" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Affiche le statut du serveur" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "affiche les téléchargements en file d'attente" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "affiche les téléchargements dans le collecteur" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Ajouter le paquet à la file d'attente" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Ajouter le paquet au collecteur" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Supprimer les fichiers de la file d'attente/du collecteur" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Supprimer les paquets de la file d'attente/du collecteur" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Déplacer les paquets de la file d'attente au collecteur ou vice versa" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Redémarrer les fichiers" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Redémarrer les paquets" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Vérifie le statut en ligne (fonctionne avec un conteneur local)" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Vérifie le statut en ligne d'un fichier conteneur" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Mettre le serveur en pause" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "continuer les téléchargements" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Basculer pause/reprendre" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "stopper le serveur" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Liste des commandes :" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Impossible d'écrire le fichier de configuration" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Vous avez besoin de py-openssl pour vous connecter à ce Core pyLoad." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adresse: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Port : " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Nom d'utilisateur: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Mot de passe : " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Les identifiants sont incorrects." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Impossible d'établir la connexion à %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Vous avez besoin de py-openssl pour vous connecter au moteur de Pyload." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Mode interactif ignoré jusqu'à ce que vous entriez des commandes." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Ajouter un paquet:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Entrez un nom pour le nouveau paquet" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Paquet : %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Analyse des liens que vous voulez ajouter." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Tapez %s une fois fini." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Liens ajoutés : " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " retour au menu principal" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Gérer les paquets:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Gérer les liens:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Que voulez-vous déplacer ?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Que voulez-vous supprimer ?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Que voulez-vous redémarrer ?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Choisissez ce que vous voulez faire ou entrez le numéro du paquet." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "supprimer" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "déplacer" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "redémarrer" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - précédent" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - suivant" + diff --git a/locale/fr/LC_MESSAGES/pyLoadGui.mo b/locale/fr/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 001412ddf..000000000 --- a/locale/fr/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/fr/LC_MESSAGES/setup.mo b/locale/fr/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index 89cb21969..000000000 --- a/locale/fr/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/fr/LC_MESSAGES/setup.po b/locale/fr/LC_MESSAGES/setup.po new file mode 100644 index 000000000..5afb2617a --- /dev/null +++ b/locale/fr/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: French\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "o" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Bienvenue dans l'Assistant de Configuration de pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Votre systÚme va être vérifié et subir un réglage de base afin de lancer pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "La valeur entre crochets [] est toujours la valeur par défaut," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "dans le cas où vous ne voulez pas la changer ou vous ne savez pas quoi choisir, appuyez sur entrée." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "N'oubliez pas : vous pouvez toujours relancer cet assistant avec l'option --setup ou -s, lorsque vous démarrez pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Si vous avez un problÚme avec cet assistant appuyer sur CTRL-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "pour annuler et ne plus le laisser démarrer automatiquement avec pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Lorsque vous êtes prêt pour la vérification du systÚme, appuyez sur entrée." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Vous avez besoin de pycurl, sqlite et python 2.5, 2.6 ou 2.7 pour exécuter pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Merci d'effectuer les corrections nécessaires et de relancer pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "Le configurateur va se fermer." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Vérification du systÚme fini, appuyer sur entrée pour voir votre rapport de status." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "décryptage des conteneurs" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "connexion ssl" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "décryptage automatique des catchas" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Interface web" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "extension Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "Fonctions disponibles :" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Fonctions indisponibles : " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto n'est pas disponible" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Vous en avez besoin si vous souhaitez décrypter les fichiers conteneurs." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL n'est pas disponible" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Vous en avez besoin si vous souhaitez établir une connexion sécurisé avec le logiciel principal ou l'interface web." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Si vous souhaitez accéder à pyLoad uniquement en local, ssl n'est pas utile." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "La Reconnaissance des catchas n'est pas disponible" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Ceci est nécessaire uniquement pour certains hÃŽtes en tant qu'utilisateur gratuit." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "Interface graphique non disponible" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "L'Interface Graphique." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "pas de moteur JavaScript trouvé" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Vous en aurez besoin pour certains liens Click'N'Load. Installez SpiderMonkey, ossp-js, pyv8 ou Rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Si vous le souhaitez, vous pouvez maintenant sortir du configurateur et corriger certaines dépendances." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Poursuivre l'installation ?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Vous voulez changer le chemin de la configuration ? Le chemin actuel est %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Si vous utilisez pyLoad sur un serveur ou si la partition home se trouve sur un disque flash il est conseillé de le modifier." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Changer le chemin de la configuration?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Vous voulez configurer les données de connexion et les paramÚtres de base ?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Ceci est recommandé pour la premiÚre exécution." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Faire le réglage de base ?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Vous voulez configurer ssl?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Configurer ssl?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Vous voulez configurer l'interface Web?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Configurer l'interface Web?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Installation terminée avec succÚs." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Appuyez sur entrée pour quitter et redémarrer pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Vérification du SystÚme ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Votre version de python est trop récente, Merci d'utiliser Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Votre version de python est trop ancienne, merci d'utiliser au moins Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Version de Python : OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Vous avez installé jinja2 version %s, elle semble trop ancienne." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Vous pouvez continuer en toute sécurité mais si l'interface web ne fonctionne pas," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "mettez à jour ou désinstallez la, pyLoad inclus une librairie jinja2 suffisante." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "moteur JS" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Configuration de base ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Les données de connexion suivantes sont valables pour le CLI, GUI et l'interface Web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Nom utilisateur" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Les clients externes (GUI, CLI ou autre) nécessitent un accÚs distant pour fonctionner sur le réseau." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Cependant, si vous souhaitez uniquement utiliser l'interface web vous pouvez le désactiver pour économiser la RAM." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Activer l'accÚs distant" + +#: module/setup.py:291 +msgid "Language" +msgstr "Langue" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Dossier de téléchargement" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Téléchargements parallÚles max" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Utiliser la reconnexion ?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Emplacement du script de reconnexion" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Configuration de l'interface Web ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Activer l'interface Web?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Adresse d'écoute, si vous utilisez 127.0.0.1 ou localhost, l'interface Web sera accessible uniquement localement." + +#: module/setup.py:312 +msgid "Address" +msgstr "Adresse" + +#: module/setup.py:313 +msgid "Port" +msgstr "Port" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad offre plusieurs serveur d'arriÚre plan, suivez maintenant une brÚve explication." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Serveur par défaut ; c'est le meilleur choix si vous ne savez pas lequel choisir." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Ce serveur permet l'utilisation de SSL ; c'est une bonne alternative à builtin." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Peut être utilisé par apache, lighttpd, mais vous oblige à les configurer, ce qui n'est pas trÚs facile." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Une alternative trÚs rapide écrite en C, nécessite libev et des connaissances en linux." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Télécharger le ici : https://github.com/jonashaag/bjoern, compilez-le" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "et copiez bjoern.so vers module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Attention : dans certain cas le serveur intégré ne marche pas, si vous avez des problÚmes avec l'interface web" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "revenez ici et changez le serveur de âintégréâ à âthreadedâ." + +#: module/setup.py:329 +msgid "Server" +msgstr "Serveur" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Configuration de SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Exécutez ces commande depuis le répertoire de configuration de pyLoad pour générer les certificats SSL :" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Si vous avez terminé et que tout s'est bien passé, vous pouvez activer le ssl maintenant." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "Activer le SSL ?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Sélectionnez une action" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Créer/modifier l'utilisateur" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Lister les utilisateurs" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Supprimer un utilisateur" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Quitter" + +#: module/setup.py:376 +msgid "Users" +msgstr "Utilisateurs" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Définition d'un nouveau dossier de configuration, la configuration actuelle ne sera pas transférée !" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Dossier de configuration" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Dossier de configuration modifié, l'assistant va se fermer, veuillez le relancer ensuite." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Appuyez sur entrée pour quitter." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "La définition du dossier de configuration a échoué : %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "%s : OK" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s : absent" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Mot de passe : " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Le mot de passe est trop court. Utilisez au moins 4 caractÚres." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Mot de passe (encore) : " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Les mots de passe ne correspondent pas." + +#: module/setup.py:493 +msgid "yes" +msgstr "oui" + +#: module/setup.py:493 +msgid "true" +msgstr "vrai" + +#: module/setup.py:493 +msgid "t" +msgstr "v" + +#: module/setup.py:496 +msgid "no" +msgstr "non" + +#: module/setup.py:496 +msgid "false" +msgstr "faux" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Entrée non valide" + diff --git a/locale/ga/LC_MESSAGES/django.po b/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 000000000..a4a148192 --- /dev/null +++ b/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Irish\n" +"Language: ga_IE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/ga/LC_MESSAGES/pyLoad.po b/locale/ga/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..c86006569 --- /dev/null +++ b/locale/ga/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Irish\n" +"Language: ga_IE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/ga/LC_MESSAGES/pyLoadCli.po b/locale/ga/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..e383ae6f0 --- /dev/null +++ b/locale/ga/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Irish\n" +"Language: ga_IE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/ga/LC_MESSAGES/setup.po b/locale/ga/LC_MESSAGES/setup.po new file mode 100644 index 000000000..006a7f1de --- /dev/null +++ b/locale/ga/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Irish\n" +"Language: ga_IE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/gl/LC_MESSAGES/django.po b/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 000000000..50f453f9e --- /dev/null +++ b/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Galician\n" +"Language: gl_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Solicitude de Novo Captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Por favor lea o texto do captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad reiniciouse" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Ãxito" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Está seguro de que quere saÃr de pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Reiniciar Ligazón" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Borrar Ligazón" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Por favor, introduza un nome ó paquete." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Por favor, prema á dereita do captcha." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Produciuse un erro." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "O cartafol está baleiro" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Fallou" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Non hai Captchas para ler." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Os contrasinais non coinciden." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Parámetros gardados." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Novo cartafol" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Está seguro de que quere reiniciar pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "esperando %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Descargas Activas" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Inicio" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Descargas" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Rexistros" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Configuración" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Información" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Progreso" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "O seu nome de usuario e contrasinal non coinciden. Por favor, inténteo de novo." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Para reiniciar os seus datos de inicio de sesión ou engadir un usuario, execute:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Borrar Terminados" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Reiniciar Falidos" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Cartafol:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Contrasinal:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Editar Paquete" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Editar os detalles do seguinte paquete." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Nome do paquete." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Nome do subcartafol para estas descargas." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Lista de contrasinais usadas para descomprimir." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Reiniciar" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Pechouse a sesión correctamente." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Ruta" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absoluto" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativo" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "nome" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "tamaño" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "tipo" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "última modificación" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "directorio pai" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "sen contido" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Engadidos" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Elixa unha selección do menú" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Válido ata" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Tráfico restante" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Tempo" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Máx. en Paralelo" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Borrar?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "inválido" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "sÃ" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "non" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Engadir Conta" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Introduza os datos da súa conta para usar caracterÃsticas premium." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "O seu nome de usuario." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "O contrasinal para esta conta." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Tipo" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Elixa un servidor para a súa conta." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Iniciar" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "anterior" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "seguinte" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Fin" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Novidades" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Soporte" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Sistema" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "S.O.:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "versión de pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Cartafol de Instalación:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Cartafol de Configuración:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Cartafol de Descarga:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Espazo Libre:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Idioma:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Porto da Interface Web:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Porto da Interface Remota:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Instalar" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Administrador de ficheiros" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Engadir Paquete" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Pegue as súas ligazóns ou suba un contedor de ligazóns." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Nome do novo paquete." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Ligazóns" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Pegue as súas ligazóns ou calquera texto aquà e prema o botón de filtrar." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtrar urls" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Contrasinal para o arquivo RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Ficheiro" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Cargar un contedor de ligazóns." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Lendo captcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "O captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Texto" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Introduza o texto no captcha." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Interface web" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "Hai unha actualización de pyLoad dispoñible!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Engadidos actualizados, por favor reinicia!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Esperando captcha" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "SaÃr" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrar" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Información" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Por favor, inicie sesión!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Deter" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Descarga:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Volverse a conectar:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Velocidade:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Activo:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Recargar páxina" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "cargando" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Volver ó principio" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "SaÃr de pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Reiniciar pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Para engadir un usuario ou cambiar contrasinais empregue:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Importante: O usuario Administrador sempre ten todos os permisos!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Cambiar Contrasinal" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "Administrador" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Permisos" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "cambiar" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Introduza o seu contrasinal actual e a desexado." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Usuario" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Contrasinal actual" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Novo contrasinal" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "O novo contrasinal." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Novo contrasinal (repetir)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Por favor, repita o seu novo contrasinal." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Non ten permisos para acceder a esta páxina." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Non se encontra o directorio de descarga." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "non dispoñible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Execute pyload.py -s para acceder á instalación." + diff --git a/locale/gl/LC_MESSAGES/pyLoad.po b/locale/gl/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..aadbdf35c --- /dev/null +++ b/locale/gl/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Galician\n" +"Language: gl_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Sinal de saÃda recibida" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad xa está executándose con pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Cambio de grupo falido: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Cambio de usuario falido: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "cartafol para os rexistros" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Comezando" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Usando directorio de inicio: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto para descodificar contedores de ligazóns" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "cartafol para ficheiros temporais" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "cartafol para as descargas" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL para conexión segura" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Movendo a antiga configuración de usuario á BD" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Por favor, comprobe os seus datos de inicio de sesión con ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Todas as ligazóns foron eliminadas" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Tempo de descarga: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Espazo libre: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Activando Contas..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Activando Engadidos..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad está funcionando" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "reiniciando pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad pechouse" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Instalar %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "non se puido atopar %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "no se puido crear %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "apagando..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "produciuse un erro mentres se apagaba" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyload terminado dende o Terminal" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "O ficheiro da base de datos eliminouse por ser dunha versión incompatible." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "O ficheiro da base de datos NON se puido converter." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "A base de datos converteuse da v2 á v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "A base de datos converteuse da v3 á v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Convertendo a antiga BD Django" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "finalizado" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "fora de liña" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "en liña" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "na cola" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "omitido" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "esperando" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "temporalmente fora de servicio" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "comezando" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "falido" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "abortado" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "descifrando" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "personalizado" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "descargando" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "procesando" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "descoñecido" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paquete finalizado: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "Usando SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Erro remoto do motor: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Iniciando %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Fallou ó cargar o motor %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "esperando %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "Certificados SSL non encontrados." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "SentÃmolo, pero retirámolo soporte para iniciar %s directamente en pyLoad" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Pode empregar o servidor con fÃos que ofrece un bo rendemento e ssl," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "por suposto pode seguir empregando o seu %s existente co servidor fastcgi de pyLoad" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "as configuracións de exemplo encóntranse no directorio module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Non pode usar %(server)s, python-flup non está instalado!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Erro importando servidor lixeiro: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "Debe descargar e compilar bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Copie o módulo boern.so ó cartafol module/lib ou use a instalación setup.py" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Evidentemente, debe estar familiarizado con linux e saber como compilar software" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Servidor en modo threaded, debido a problemas de rendemento coñecidos en windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Este servidor non ofrece SSL, por favor considere usar o servidor con fÃos no seu lugar" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Iniciando servidor web incorporado: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Iniciando servidor web SSL con fÃos: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Iniciando servidor web con fÃos: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Iniciando servidor fastcgi: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Iniciando servidor web lixeiro (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Non ten permisos para acceder a esta páxina." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Non se encontra o directorio de descarga." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "non dispoñible" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Execute pyload.py -s para acceder á instalación." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Descarga por partes falida, conexión única de emerxencia| %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Iniciando descarga: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Descarga finalizada: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "O engadido %s non atopa ningunha función." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Descarga cancelada: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Descarga reiniciada: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "A descarga está fóra de servizo: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "A descarga está temporalmente fora de servizo: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Descarga falida: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "No se puido conectar ó servidor ou conexión reiniciada, esperando 1 minuto e tentando de novo." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Descarga omitida: %(name)s debido a %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Comeza o descifrado: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Descifrado falido: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Reintentando %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "A Obtención de información para %(name)s fallou | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Erro executando as ligazóns: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Fallou a activación de %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Engadidos activados: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Engadidos desactivados: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Reconexión Falida: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Non se atopou o script de reconexión!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Iniciando reconexión" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Fallo executando o script de reconexión!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Conectado de novo, nova dirección IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Non hai suficiente espazo libre no dispositivo" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Non se puido iniciar sesión coa conta %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Contrasinal erróneo" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "A hora %s ten un formato incorrecto, use: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "A conta %s non ten tráfico suficiente, comprobarase outra vez en 30min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "A conta %s expirou, compróbea de novo en 1h" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "Limite de descargas alcanzado" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s ten un patrón inválido." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Erro importando %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Non se cargou ningún servidor" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Active a descarga directa na súa conta de Bitshare" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "A lista de ligazóns non se puido limpar." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Configuración da conta borrada, debido ó formato da nova configuración." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Autorización requirida (usuario:contrasinal)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Arquivo non dispoñible temporalmente" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: esperando entre descargas %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: esperando captcha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "O arquivo descargado estaba baleiro" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "Clave de API inválida" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: Non queda suficiente tráfico" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Tráfico excedido" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Tráfico compartido (descarga directa)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Xa está descargando dende esta dirección ip, esperando 60 segundos" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Código de Autenticación Inválido, a descarga reiniciarase" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: No quedan espazos dispoñibles" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Precisa dunha conta premium para este arquivo" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Nome do arquivo inválido" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Erro con descargas en paralelo, esperando 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Non iniciou sesión." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "O ficheiro non existe." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Os engadidos foron actualizados, por favor reinicie pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Engadidos actualizados e cargados de novo" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Non hai actualizacións de engadidos dispoñibles" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "No hai actualizacións para pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Nova versión %s de pyLoad dispoñible ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Obtéñaa aquÃ: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Imposible conectar co servidor para actualizacións" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nova versión de %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Erro mentres se actualizaba %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "Non coincide a versión" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Descarga finalizada: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nova Petición de Captcha: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Responda con 'c %s texto ó captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Engadido %s dende HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "%s non instalado" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Non se puido activar %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Activado" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Non se activaron os engadidos de extracción" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Paquete %s posto na cola para a súa extracción posterior" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Comprobar paquete %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Extraer a %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "extraendo" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Protexido con contrasinal" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Contrasinal erróneo" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Borrando ficheiros %s" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Extracción finalizada" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Erro de Arquivo" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "O CRC non coincide" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Erro Descoñecido" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Configuración de Usuario e Grupo falida" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: O porto 9666 xa está en uso" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s créditos restantes" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "A súa conta de CaptchaTrader non ten créditos suficientes" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Descarga finalizada: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Scripts instalados para %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Script non executable:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Erro en %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Por favor, engada primeiro a súa conta rehost.to e reinicie pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil e tesseract non están instalados e no hai cliente conectado para descifrar o captcha" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Non se obtiveron resultados para o captcha no tempo asignado de ningún dos engadidos." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Configuración de Usuario e Grupo falida: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Non hai cliente conectado para descifrar o captcha" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Engadido o paquete %(name)s que contén %(count)d ligazóns" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Engadidos %(count)d ligazóns ó paquete #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Non se detectou ningún motor de js, por favor instale Spidermonkey, ossp-js, pyv8 ou rhino" + diff --git a/locale/gl/LC_MESSAGES/pyLoadCli.po b/locale/gl/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..4b1bbb714 --- /dev/null +++ b/locale/gl/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Galician\n" +"Language: gl_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Interface de Liña de Comandos" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s Descargas:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Velocidade: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Tamaño: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Finalizado en: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "esperando: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Menú:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Engadir Ligazóns" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Administrar Cola" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " Administrar Colector" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " Retomar/Deter Servidor" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Parar Servidor" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " SaÃr" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Por favor use esta sintaxe: add <Package name> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Comprobando %d ligazóns:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "O ficheiro non existe." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad terminou" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Amosa-lo estado do servidor" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Amosa-las descargas en cola" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Amosa-las descargas en colector" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Engadir paquetes á cola" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Engadir paquetes ó colector" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Borrar Ficheiros da Cola/Colector" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Borrar Paquetes da Cola/Colector" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Mover os Paquetes da Cola ó Colector ou viceversa" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Reiniciar ficheiros" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Reiniciar paquetes" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Comprobar o estado da conexión, traballa cun contedor local" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Comprobar o estado en liña dun contedor" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Pausa o servidor" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "continuar as descargas" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Alternar deter/continuar" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "finalizar servidor" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Lista de comandos:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Resultou imposÃbel escribir no ficheiro de configuración do usuario" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Necesita py-openssl para conectarse a este Núcleo de pyLoad." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Enderezo: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Porto: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Nome de usuario: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Contrasinal: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Os datos de inicio de sesión son incorrectos." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Non se puido establecer a conexión a %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Necesita py-openssl para conectarse a este núcleo pyLoad." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Modo interactivo ignorado, xa que pasou algúns comandos." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Engadir Paquete:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Introduza un nome para o novo paquete" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Paquete: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Procesar as ligazóns que desexe engadir." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Teclee %s cando remate." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Ligazóns engadidos: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " volver ó menú principal" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Administrar Paquetes:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Administrar Ligazóns:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Que quere mover?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Que quere borrar?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Que quere reiniciar?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Elixa o que queira facer ou introduza o número do paquete." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "borrar" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "mover" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "reiniciar" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - anterior" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - seguinte" + diff --git a/locale/gl/LC_MESSAGES/setup.po b/locale/gl/LC_MESSAGES/setup.po new file mode 100644 index 000000000..b04099b35 --- /dev/null +++ b/locale/gl/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Galician\n" +"Language: gl_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "s" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Benvido ó Asistente de Configuración de pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Revisarase o seu sistema e farase unha configuración básica para executar pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "O valor entre corchetes [] sempre é o valor por defecto," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "en caso de que non queira cambialo ou non estea seguro de que opción elixir, só prema entrar." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Non o esqueza: Sempre pode volver a executar este asistente co parámetro --setup ou -s cando inicie pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Se ten algún problema co asistente presione Ctrl-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "para abortar e non permitirlle volver a iniciarse automaticamente con pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Cando estea listo para a comprobación do sistema, prema entrar." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Precisa pycurl, sqlite e python 2.5, 2.6 ou 2.7 para executar pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Por favor corrixa isto e volva a executar pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "O asistente da instalación pecharase." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "A comprobación do sistema concluÃu, prema entrar para ver o informe de estado." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Estado ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "descifrando contedor" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "conexión ssl" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "descifrado automático de captcha" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Interface web" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "extensión Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "CaracterÃsticas dispoñibles:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "CaracterÃsticas non dispoñibles: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto non dispoñible" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Precisa disto se quere descifrar arquivos de contedores." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL non dispoñible" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Isto é necesario se quere establecer unha conexión segura co núcleo ou a interface web." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "SSL non é útil se tan só quere acceder a pyLoad localmente." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "recoñecemento de Captcha non dispoñible" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Só necesario para algúns servidores e como usuario gratuÃto." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "Gui non dispoñible" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "A Interface de Usuario Gráfica." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "motor de JavaScript non atopado" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Precisará disto para algunhas ligazóns Click'N'Load. Instale Spidermonkey, ossp-js, pyv8 ou rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Pode cancelar o asiste agora e corrixir algunhas dependencias se quere." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Desexa continuar co asistente?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Quere cambiar a ruta de configuración? Actualmente é %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Si usa pyLoad en un servidor ou a partición primaria reside nunha memoria flash interna, pode ser boa idea cambiala." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Cambia-la ruta de configuración?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Quere configurar os datos de acceso e a configuración básica?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Isto recoméndase na primeira execución." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Facer a configuración básica?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Quere configurar ssl?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Configurar ssl?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Quere configurar a interface web?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Configurar a interface web?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Configuración rematada correctamente." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Prema entrar para saÃr e reiniciar pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Comprobación do sistema ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "A súa versión de python é demasiado nova, por favor use Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "A súa versión de python é demasiado antiga, por favor use polo menos Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Versión de Python: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "A súa versión %s de jinja2 instalada parece demasiado antiga." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Pode continuar de maneira segura pero se a interface web non funcionara," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "por favor actualÃcea ou elimÃnea, pyLoad inclúe unha biblioteca jinja2 suficiente." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "Motor JS" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Configuración Básica ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Os seguintes datos de acceso son válidos para CLI, GUI e interface web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Os clientes externos (GUI, CLI ou outros) precisan acceso remoto para traballar a través da rede." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Non obstante, se só quere utilizar interface web pode desactivalo para aforrar ram." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Activar acceso remoto" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Cartafol de descargas" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Máximas descargas paralelas" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Usar reconectar?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Lugar do script de reconexión" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Configuración da Interface Web ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Activar a interface web?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Dirección de escoita, se usa 127.0.0.1 ou localhost, a interface web só poderá ser accesible localmente." + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad ofrece varias infraestruturas de servidores, a continuación unhas pequenas explicacións." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "O servidor por defecto, a mellor opción se non sabe cal elixir." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Este servidor ofrece SSL e é unha boa alternativa ó integrado." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Pode usalo apache, lighttpd, require que o configure, o cal non é unha tarefa fácil." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Unha alternativa moi rápida escrita en C, require libev e coñecementos de linux." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Obtéñao aquÃ: https://github.com/jonashaag/bjoern, e compÃleo" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "e copie bjoern.so a module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Atención: Nalgúns casos raros o servidor integrado non funciona, se nota problemas coa interface web" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "volva aquà e cambie o servidor integrado polo servidor con fÃos." + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Configuración de SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Execute estes comandos dende o cartafol de configuración de pyLoad para crear os certificados ssl:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Se xa terminou e todo rematou ben, poderá activar ssl agora." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "Activar SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Elixa unha acción" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Crear/Editar usuario" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Listar usuarios" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Eliminar usuario" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - SaÃr" + +#: module/setup.py:376 +msgid "Users" +msgstr "Usuarios" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Configurando o novo directorio de configuración, os parámetros actuais non se transferirán!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Ruta de configuración" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Ruta de configuración cambiada, a instalación pecharase, por favor reinicie para continuar." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Prema Entrar para saÃr." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Axuste da ruta de configuración falida: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: non atopado" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Contrasinal: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Contrasinal (de novo): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Os contrasinais non coinciden." + +#: module/setup.py:493 +msgid "yes" +msgstr "sÃ" + +#: module/setup.py:493 +msgid "true" +msgstr "verdadeiro" + +#: module/setup.py:493 +msgid "t" +msgstr "v" + +#: module/setup.py:496 +msgid "no" +msgstr "non" + +#: module/setup.py:496 +msgid "false" +msgstr "falso" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Ingreso non válido" + diff --git a/locale/gui.pot b/locale/gui.pot deleted file mode 100644 index dc74397a0..000000000 --- a/locale/gui.pot +++ /dev/null @@ -1,511 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR pyLoad Team -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: pyLoad 0.4.9\n" -"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" -"POT-Creation-Date: 2011-12-07 19:21+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: pyLoadGui.py:290 -msgid "paused" -msgstr "" - -#: pyLoadGui.py:292 -msgid "running" -msgstr "" - -#: pyLoadGui.py:332 -msgid "Unnamed" -msgstr "" - -#: pyLoadGui.py:655 -#, python-format -msgid "Finished downloading of '%s'" -msgstr "" - -#: pyLoadGui.py:657 -#, python-format -msgid "Failed downloading '%s'!" -msgstr "" - -#: pyLoadGui.py:660 -#, python-format -msgid "Added '%s' to queue" -msgstr "" - -#: pyLoadGui.py:685 -msgid "Connection lost" -msgstr "" - -#: pyLoadGui.py:685 -msgid "Lost connection to the core!" -msgstr "" - -#: pyLoadGui.py:720 -msgid "Show" -msgstr "" - -#: pyLoadGui.py:725 module/gui/MainWindow.py:133 -msgid "Exit" -msgstr "" - -#: module/gui/Connector.py:76 -msgid "bad login credentials" -msgstr "" - -#: module/gui/Connector.py:78 -msgid "no ssl support" -msgstr "" - -#: module/gui/Connector.py:80 -msgid "can't connect to host" -msgstr "" - -#: module/gui/Connector.py:94 -#, python-format -msgid "server is version %(new)s client accepts version %(current)s" -msgstr "" - -#: module/gui/Collector.py:47 -msgid "finished" -msgstr "" - -#: module/gui/Collector.py:48 -msgid "offline" -msgstr "" - -#: module/gui/Collector.py:49 -msgid "online" -msgstr "" - -#: module/gui/Collector.py:50 -msgid "queued" -msgstr "" - -#: module/gui/Collector.py:51 -msgid "skipped" -msgstr "" - -#: module/gui/Collector.py:52 -msgid "waiting" -msgstr "" - -#: module/gui/Collector.py:53 -msgid "temp. offline" -msgstr "" - -#: module/gui/Collector.py:54 -msgid "starting" -msgstr "" - -#: module/gui/Collector.py:55 -msgid "failed" -msgstr "" - -#: module/gui/Collector.py:56 -msgid "aborted" -msgstr "" - -#: module/gui/Collector.py:57 -msgid "decrypting" -msgstr "" - -#: module/gui/Collector.py:58 -msgid "custom" -msgstr "" - -#: module/gui/Collector.py:59 -msgid "downloading" -msgstr "" - -#: module/gui/Collector.py:60 -msgid "processing" -msgstr "" - -#: module/gui/Collector.py:284 module/gui/PackageDock.py:66 -#: module/gui/Queue.py:152 -msgid "Name" -msgstr "" - -#: module/gui/Collector.py:286 module/gui/Queue.py:156 -msgid "Plugin" -msgstr "" - -#: module/gui/Collector.py:288 module/gui/Queue.py:154 -msgid "Status" -msgstr "" - -#: module/gui/Collector.py:290 module/gui/Queue.py:158 -msgid "Size" -msgstr "" - -#: module/gui/Accounts.py:75 -msgid "not valid" -msgstr "" - -#: module/gui/Accounts.py:77 module/gui/Accounts.py:207 -msgid "n/a" -msgstr "" - -#: module/gui/Accounts.py:80 -msgid "%a, %d %b %Y %H:%M" -msgstr "" - -#: module/gui/Accounts.py:83 module/gui/Accounts.py:205 -msgid "unlimited" -msgstr "" - -#: module/gui/Accounts.py:138 module/gui/AccountEdit.py:38 -msgid "Type" -msgstr "" - -#: module/gui/Accounts.py:140 module/gui/AccountEdit.py:39 -msgid "Login" -msgstr "" - -#: module/gui/Accounts.py:142 -msgid "Valid until" -msgstr "" - -#: module/gui/Accounts.py:144 -msgid "Traffic left" -msgstr "" - -#: module/gui/SettingsWidget.py:74 -msgid "General" -msgstr "" - -#: module/gui/SettingsWidget.py:75 -msgid "Plugins" -msgstr "" - -#: module/gui/SettingsWidget.py:89 -msgid "Reload" -msgstr "" - -#: module/gui/SettingsWidget.py:90 module/gui/ConnectionManager.py:206 -#: module/gui/AccountEdit.py:53 -msgid "Save" -msgstr "" - -#: module/gui/SettingsWidget.py:192 -msgid "Yes" -msgstr "" - -#: module/gui/SettingsWidget.py:193 -msgid "No" -msgstr "" - -#: module/gui/ConnectionManager.py:42 module/gui/ConnectionManager.py:185 -msgid "pyLoad ConnectionManager" -msgstr "" - -#: module/gui/ConnectionManager.py:47 -msgid "New" -msgstr "" - -#: module/gui/ConnectionManager.py:48 module/gui/MainWindow.py:324 -msgid "Edit" -msgstr "" - -#: module/gui/ConnectionManager.py:49 module/gui/MainWindow.py:275 -#: module/gui/MainWindow.py:295 module/gui/MainWindow.py:323 -msgid "Remove" -msgstr "" - -#: module/gui/ConnectionManager.py:50 -msgid "Connect" -msgstr "" - -#: module/gui/ConnectionManager.py:56 -msgid "Connect:" -msgstr "" - -#: module/gui/ConnectionManager.py:73 -msgid "Use internal Core:" -msgstr "" - -#: module/gui/ConnectionManager.py:117 -#, python-format -msgid "%s (Default)" -msgstr "" - -#: module/gui/ConnectionManager.py:190 -msgid "Name:" -msgstr "" - -#: module/gui/ConnectionManager.py:191 -msgid "Host:" -msgstr "" - -#: module/gui/ConnectionManager.py:192 -msgid "Local:" -msgstr "" - -#: module/gui/ConnectionManager.py:193 -msgid "User:" -msgstr "" - -#: module/gui/ConnectionManager.py:194 -msgid "Password:" -msgstr "" - -#: module/gui/ConnectionManager.py:195 -msgid "Port:" -msgstr "" - -#: module/gui/ConnectionManager.py:207 module/gui/CaptchaDock.py:65 -msgid "Cancel" -msgstr "" - -#: module/gui/MainWindow.py:44 -msgid "pyLoad Client" -msgstr "" - -#: module/gui/MainWindow.py:92 -msgid "Packages:" -msgstr "" - -#: module/gui/MainWindow.py:96 -msgid "Files:" -msgstr "" - -#: module/gui/MainWindow.py:100 -msgid "Status:" -msgstr "" - -#: module/gui/MainWindow.py:104 -msgid "Space:" -msgstr "" - -#: module/gui/MainWindow.py:108 -msgid "Speed:" -msgstr "" - -#: module/gui/MainWindow.py:129 -msgid "File" -msgstr "" - -#: module/gui/MainWindow.py:130 -msgid "Connections" -msgstr "" - -#: module/gui/MainWindow.py:134 -msgid "Connection manager" -msgstr "" - -#: module/gui/MainWindow.py:156 -msgid "Overview" -msgstr "" - -#: module/gui/MainWindow.py:157 -msgid "Queue" -msgstr "" - -#: module/gui/MainWindow.py:158 -msgid "Collector" -msgstr "" - -#: module/gui/MainWindow.py:159 -msgid "Accounts" -msgstr "" - -#: module/gui/MainWindow.py:160 -msgid "Settings" -msgstr "" - -#: module/gui/MainWindow.py:161 -msgid "Log" -msgstr "" - -#: module/gui/MainWindow.py:190 -msgid "Hide Toolbar" -msgstr "" - -#: module/gui/MainWindow.py:194 -msgid "Toggle Pause/Resume" -msgstr "" - -#: module/gui/MainWindow.py:200 -msgid "Stop" -msgstr "" - -#: module/gui/MainWindow.py:202 module/gui/MainWindow.py:302 -#: module/gui/MainWindow.py:322 -msgid "Add" -msgstr "" - -#: module/gui/MainWindow.py:204 -msgid "Check Clipboard" -msgstr "" - -#: module/gui/MainWindow.py:211 module/gui/MainWindow.py:308 -#: module/gui/Overview.py:101 -msgid "Package" -msgstr "" - -#: module/gui/MainWindow.py:212 module/gui/MainWindow.py:309 -msgid "Container" -msgstr "" - -#: module/gui/MainWindow.py:213 -msgid "Account" -msgstr "" - -#: module/gui/MainWindow.py:214 module/gui/MainWindow.py:310 -msgid "Links" -msgstr "" - -#: module/gui/MainWindow.py:238 -msgid "Push selected packages to queue" -msgstr "" - -#: module/gui/MainWindow.py:261 -msgid "New Account" -msgstr "" - -#: module/gui/MainWindow.py:276 module/gui/MainWindow.py:298 -msgid "Restart" -msgstr "" - -#: module/gui/MainWindow.py:277 -msgid "Pull out" -msgstr "" - -#: module/gui/MainWindow.py:278 -msgid "Abort" -msgstr "" - -#: module/gui/MainWindow.py:279 module/gui/MainWindow.py:297 -msgid "Edit Name" -msgstr "" - -#: module/gui/MainWindow.py:296 -msgid "Push to queue" -msgstr "" - -#: module/gui/MainWindow.py:299 -msgid "Refresh Status" -msgstr "" - -#: module/gui/MainWindow.py:402 -#, python-format -msgid "All Container Types (%s)" -msgstr "" - -#: module/gui/MainWindow.py:403 -#, python-format -msgid "DLC (%s)" -msgstr "" - -#: module/gui/MainWindow.py:404 -#, python-format -msgid "CCF (%s)" -msgstr "" - -#: module/gui/MainWindow.py:405 -#, python-format -msgid "RSDF (%s)" -msgstr "" - -#: module/gui/MainWindow.py:406 -#, python-format -msgid "Text Files (%s)" -msgstr "" - -#: module/gui/MainWindow.py:408 -msgid "Open container" -msgstr "" - -#: module/gui/PackageDock.py:25 -msgid "New Package" -msgstr "" - -#: module/gui/PackageDock.py:68 -msgid "Password" -msgstr "" - -#: module/gui/PackageDock.py:71 -msgid "Links in this Package" -msgstr "" - -#: module/gui/PackageDock.py:77 -msgid "Create" -msgstr "" - -#: module/gui/PackageDock.py:78 -msgid "Filter URLs" -msgstr "" - -#: module/gui/CaptchaDock.py:29 -msgid "Captcha" -msgstr "" - -#: module/gui/CaptchaDock.py:64 -msgid "OK" -msgstr "" - -#: module/gui/AccountEdit.py:32 -msgid "Edit account" -msgstr "" - -#: module/gui/AccountEdit.py:40 -msgid "New password" -msgstr "" - -#: module/gui/AccountEdit.py:83 -msgid "Create account" -msgstr "" - -#: module/gui/Queue.py:160 -msgid "ETA" -msgstr "" - -#: module/gui/Queue.py:162 -msgid "Progress" -msgstr "" - -#: module/gui/Queue.py:384 -#, python-format -msgid "waiting %d seconds" -msgstr "" - -#: module/gui/Overview.py:71 module/gui/Overview.py:152 -msgid "Downloading" -msgstr "" - -#: module/gui/Overview.py:83 -msgid "Queued" -msgstr "" - -#: module/gui/Overview.py:147 -msgid "ETA: " -msgstr "" - -#: module/gui/Overview.py:149 -msgid "Parts: " -msgstr "" - -#: module/gui/Overview.py:151 -msgid "Finished" -msgstr "" - -#: module/gui/Overview.py:155 -#, python-format -msgid "Speed: %s" -msgstr "" - -#: module/gui/Overview.py:158 module/gui/Overview.py:160 -msgid "Size:" -msgstr "" diff --git a/locale/he/LC_MESSAGES/django.po b/locale/he/LC_MESSAGES/django.po new file mode 100644 index 000000000..50815063b --- /dev/null +++ b/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hebrew\n" +"Language: he_IL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/he/LC_MESSAGES/pyLoad.po b/locale/he/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..d5efc9f35 --- /dev/null +++ b/locale/he/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hebrew\n" +"Language: he_IL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/he/LC_MESSAGES/pyLoadCli.po b/locale/he/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..59cc71646 --- /dev/null +++ b/locale/he/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hebrew\n" +"Language: he_IL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/he/LC_MESSAGES/setup.po b/locale/he/LC_MESSAGES/setup.po new file mode 100644 index 000000000..1e1bacb56 --- /dev/null +++ b/locale/he/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hebrew\n" +"Language: he_IL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/hi/LC_MESSAGES/django.po b/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 000000000..71cf38b32 --- /dev/null +++ b/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hindi\n" +"Language: hi_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/hi/LC_MESSAGES/pyLoad.po b/locale/hi/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..5afc82339 --- /dev/null +++ b/locale/hi/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hindi\n" +"Language: hi_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/hi/LC_MESSAGES/pyLoadCli.po b/locale/hi/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..4737f6785 --- /dev/null +++ b/locale/hi/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hindi\n" +"Language: hi_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s à€¡à€Ÿà€à€šà€²à¥à€¡:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " à€à€€à€¿: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " à€à€à€Ÿà€°: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " à€à€à€¡à¥: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "à€ªà¥à€°à€€à¥à€à¥à€·à€Ÿ à€®à¥à€ :" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "à€žà¥à€¥à€¿à€€à€¿:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "à€à¥à€² à€à€€à€¿" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "à€à¥à€²" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "à€®à¥à€šà¥à€¯à¥ " + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "à€²à€¿à€à€à¥à€ž à€à¥à€¡à€Œà¥à€" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "à€¡à€Ÿà€à€šà€²à¥à€¡ à€à€Ÿà€°à¥ à€°à€à¥à€ " + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "à€žà€°à¥à€µà€° à€¬à€à€Š à€à€°à¥à€ " + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "à€à€®à€Ÿà€à€¡ à€žà¥à€à¥ " + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "à€ªà¥à€°à¥à€: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "à€à€ªà€¯à¥à€à€à€°à¥à€€à€Ÿ à€šà€Ÿà€®: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "à€ªà€Ÿà€žà€µà€°à¥à€¡: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "à€ªà¥à€à¥à€ à€à¥à€¡à€Œà¥à€:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "à€šà€ à€ªà¥à€à¥à€ à€à¥ à€šà€Ÿà€® à€Šà¥à€ " + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "à€ªà¥à€à¥à€: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "à€ªà¥à€°à€Ÿ à€¹à¥à€šà¥ à€ªà€° %s à€à€Ÿà€à€ª à€à€°à¥à€ " + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "à€à¥à¥à¥ à€à€ à€²à€¿à€à€" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "à€®à¥à€à¥à€¯à€Ÿ à€®à¥à€šà¥à€¯à¥ à€ªà€° à€µà€Ÿà€ªà€ž à€à€Ÿà€à€ " + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "à€®à€¿à€à€Ÿà€¯à¥à€ " + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "à€ªà¥à€šà€à€à€°à€à€ à€à€°à¥à€ " + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "-à€ªà€¿à€à€²à€Ÿ " + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "-à€
à€à€²à€Ÿ " + diff --git a/locale/hi/LC_MESSAGES/setup.po b/locale/hi/LC_MESSAGES/setup.po new file mode 100644 index 000000000..3ecfc5a1b --- /dev/null +++ b/locale/hi/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hindi\n" +"Language: hi_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "à€ªà€Ÿà€žà€µà€°à¥à€¡: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/hr/LC_MESSAGES/django.po b/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 000000000..fbaa25c79 --- /dev/null +++ b/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Croatian\n" +"Language: hr_HR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/hr/LC_MESSAGES/pyLoad.po b/locale/hr/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..cb81932ca --- /dev/null +++ b/locale/hr/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Croatian\n" +"Language: hr_HR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/hr/LC_MESSAGES/pyLoadCli.po b/locale/hr/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..ba9048e0c --- /dev/null +++ b/locale/hr/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Croatian\n" +"Language: hr_HR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/hr/LC_MESSAGES/setup.po b/locale/hr/LC_MESSAGES/setup.po new file mode 100644 index 000000000..b4ef5c976 --- /dev/null +++ b/locale/hr/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Croatian\n" +"Language: hr_HR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/hu/LC_MESSAGES/django.po b/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 000000000..f2c1135d8 --- /dev/null +++ b/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hungarian\n" +"Language: hu_HU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Ãj Captcha kérés" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Olvasd el a captcha-n levÅ szöveget." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad újraindÃtva" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "ki" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Sikeres" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "be" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Biztos bezárod a pyLoad-ot?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Link újraindÃtás" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Link törlése" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Add meg a csomag nevét." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Kattints a megfelelÅ captcha helyre." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Hiba történt." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Ãres könyvtár" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Sikertelen" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Nincs Captcha." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "A jelszavak nem egyeznek." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "BeállÃtások elmentve." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Ãj könyvtár" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Biztos újraindÃtod a pyLoad-ot?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "várakozás %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "AktÃv letöltések" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "FÅoldal" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Letöltések" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Napló" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "BeállÃtások" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Név" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Ãllapot" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Információ" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Méret" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Folyamat" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Bejelentkezés" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Felhasználónév" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Jelszó" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "A felhasználói név és a jelszó nem egyezik. Próbáld újra." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "A bejelentkezési adatok törléséhez vagy új felhasználó felvételéhez futtasd:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Sikeresek törlése" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Sikertelenek újrapróbálása" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Könyvtár:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Jelszó:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Csomag szerkesztése" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Csomag részletei." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Csomag neve." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "mappa" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Alkönyvtár a letöltéseknek." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Jelszavak a kitömörÃtéshez." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "KÃŒldés" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Alaphelyzet" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Sikeresen kijelentkeztél." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Elérési útvonal" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "abszolút" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relatÃv" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "név" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "méret" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "tÃpus" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "utolsó módosÃtás" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "szÃŒlÅ könyvtár" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "nincs tartalom" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Ãltalános" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "BeépÃŒlÅk" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Hozzáférések" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Válaszd ki a megfelelÅ szekciót a menÃŒbÅl" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "BeépÃŒlÅ" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "Prémium" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Lejár" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "HátralévÅ adatforgalom" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "IdÅ" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Max. egyszerre futó" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Törlés?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "érvényes" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "érvénytelen" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "igen" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "nem" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Hozzáad" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Fiók hozzáadása" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Add meg a prémium hozzáféréshez szÃŒkséges adatokat." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Felhasználói neved." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Jelszó ehhez a hozzáféréshez." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "TÃpus" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Válaszd ki a hozzáférésedhez tartozó ellátót." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "IndÃt" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "elÅzÅ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "következÅ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Vége" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "HÃrek" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "SegÃtségnyújtás" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Rendszer" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad verzió:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "TelepÃtés helye:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "BeállÃtások helye:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Letöltések helye:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Szabad terÃŒlet:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Nyelv:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Web felÃŒlet port:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Távoli elérés port:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "BeállÃtás" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Ãllomány kezelÅ" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Csomag hozzáadása" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Illesztd be a linkeket, vagy tölts fel egy gyűjtÅt." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Az új csomag neve." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Linkek" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Illesztd be a linkeket, vagy bármilyen szöveget és nyomj a linkek szűrésére." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Linkek kiszűrése" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Jelszó a RAR állományhoz" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Ãllomány" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "GyűjtÅ feltöltése." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Cél" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Captcha olvasás" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "A captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Szöveg" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Add meg a captcha-n található szöveget." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Bezárás" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Webes felÃŒlet" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad frissÃtés elérhetÅ!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "BeépÃŒlÅk frissÃtve, indÃtsd újra!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha várakozik" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Kijelentkezés" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Adminisztrálás" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Infó" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Kérlek jelentkezz be!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "MegállÃt" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Mégse" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Letöltés:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Ãjracsatlakozás:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Sebesség:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "AktÃv:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Oldal frissÃtése" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "betöltés" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Vissza a tetejére" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "pyLoad bezárása" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "pyLoad újraindÃtása" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Ãj felhasználó hozzáadásához vagy jelszó változtatáshoz:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Fontos: Az Admin felhasználó mindig teljes jogkörrel rendelkezik!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Jelszó változtatás" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Engedélyek" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "változtat" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "A jelenlegi és a kÃvánt jelszó." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Felhasználó" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Jelenlegi jelszó" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Ãj jelszó" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Az új jelszó." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Ãj jelszó (ismét)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Ismételd meg az új jelszót." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Nincs jogosultságod a lap megtekintéséhez." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Letöltési könyvtár nem található." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "végtelen" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "nem elérhetÅ" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "A beállÃtáshoz futtasd: pyload.py -s." + diff --git a/locale/hu/LC_MESSAGES/pyLoad.po b/locale/hu/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..84f94d435 --- /dev/null +++ b/locale/hu/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hungarian\n" +"Language: hu_HU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "LeállÃtási jel érkezett" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "a pyLoad már fut az alábbi pid számmal: %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Sikertelen csoport váltás: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Sikertelen felhasználó váltás: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "könyvtár a naplóknak" + +#: module/Core.py:340 +msgid "Starting" +msgstr "IndÃtás" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "FÅkönyvtár használata: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto a konténer fájlok dekódolásához" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "könyvtár az átmeneti fájloknak" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "könyvtár a letöltéseknek" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL a biztonságos kapcsolathoz" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "EllenÅrizd a belépési adataid a következÅ paranccsal: ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Minden link törölve" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Letöltési idÅ: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Szabad hely: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Hozzáférések aktiválása..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "BÅvÃtmények aktiválása..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad fut" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "pyLoad újraindÃtása" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad kilép" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "TelepÃtés %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "leállÃtás..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "hiba leállÃtás közben" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyLoad kilÅve konzolról" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "befejezett" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "várólistán" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "átugorva" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "várakozás" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "átmenetileg offline" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "indÃtás" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "sikertelen" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "megszakÃtott" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "dekódolás" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "egyéni" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "letöltés" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "feldolgozás alatt" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "ismeretlen" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Kész csomag: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "SSL ThriftBackend használata" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Távoli hiba: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "IndÃtás: %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Backend betöltése sikertelen: %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "várakozás %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL tanúsÃtvány nem található." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Ez a szerver nem támogatja az SSL-t, kérlek használj helyette másikat" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Nincs jogosultságod a lap megtekintéséhez." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Letöltési könyvtár nem található." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "végtelen" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "nem elérhetÅ" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "A beállÃtáshoz futtasd: pyload.py -s." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Darabokban letöltés sikertelen, visszatérés egyszeri kapcsolatra | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Letöltés elindÃtva: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Letöltés befejezve: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "A %s bÅvÃtménybÅl hiányzik egy funkció." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Letöltés megszakÃtva: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Letöltés újraindÃtva: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "A letöltés offline: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "A letöltés átmenetileg offline: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "A letöltés sikertelen: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Nem sikerÃŒlt csatlakozni a cÃmhez, újrapróbálás 1 perc múlva." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Letöltés átugorva: %(name)s - %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Dekódolás elkezdve: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Dekódolás sikertelen: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Ãjra próbálkozás %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "%(name)s információinak lekérése sikertelen | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Sikertelen aktiválás: %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Ãjracsatlakozás sikertelen: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Ãjracsatlakozó script nem található!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Ãjracsatlakozás indÃtása" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Az újracsatlakozó scriptet nem sikerÃŒlt futtatni!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Ãjracsatlakozva, új IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Nincs elég hely az eszközön" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Nem sikerÃŒlt bejelentkezni: %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Hibás jelszó" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "%s hozzáférésen nincs elég adatforgalom, újra próbálás: 30 perc" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "%s hozzáférés lejárt, újra próbálás: 1 óra" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "A letöltési korlát elérve" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Hiba a(z) %(name)s betöltése közben: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Nincs szolgáltató betöltve" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Közvetlen letöltés aktiválása a Bitshare hozzáférésen" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "AzonosÃtás szÃŒkséges (felhasználónév:jelszó)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Add meg a(z) %s hozzáférés adatait, vagy deaktiváld ezt a beépÃŒlÅt" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "HTML kód van a letöltött fájlban (%s). Lehet, hogy átirányÃtási hiba, a letöltés újra lesz indÃtva." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Ãllomány átmenetileg nem elérhetÅ" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: letöltések közti várakozás %d mp." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: captcha-ra várakozás %d mp." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "A letöltött fájl ÃŒres" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "Ãrvénytelen API kulcs" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: Nincs elég adatforgalom hátra" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Adatforgalom túllépve" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Adatforgalom megosztás (közvetlen letöltés)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Már van folyamatban letöltés errÅl az IP-rÅl, várakozás: 60mp" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Hibás Auth kód, a letöltés újraindÃtása" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: Nincs ingyenes hely" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Ehhez a fájlhoz prémium hozzáférés szÃŒkséges" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Hibás fájlnév" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Többszálas letöltés hiba, várakozás: 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Nem vagy bejelentkezve." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Sikertelen dekódolás" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "Nincs fájl kulcs az URL-ben" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Hibakód:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** BÅvÃtmények frissÃtve, indÃtsd újra a pyLoad-ot ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "BÅvÃtmények frissÃtve és betöltve" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Nincs bÅvÃtmény frissÃtés" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Nincs új pyLoad verzió" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Ãj pyLoad verzió elérhetÅ: %s ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Letöltés: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Nem sikerÃŒlt a szerverhez csatlakozni a frissÃtésekért" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Ãj verzió: %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Hiba frissÃtés közben %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "verzió ÃŒtközés" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Letöltés befejezve: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Ãj captcha kérés: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Válaszolj ezzel: 'c %s szöveg a captcha-n'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "ElÅször adj meg rehost.to hozzáférést majd indÃtsd újra a pyLoad-ot" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "%s HotFolder-bÅl hozzáadva" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "Nincs %s telepÃtve" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Nem sikerÃŒlt aktiválni: %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Aktivált" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Nincs kicsomagoló bÅvÃtmény aktiválva" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "%s csomag a várólistán késÅbbi kitömörÃtésre" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Csomag ellenÅrzése: %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Kicsomagolás: %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Nincs kitömörÃthetÅ fájl" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "kicsomagolás" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Jelszóval védett" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Hibás jelszó" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "%s fájl törlése" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Kicsomagolás kész" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "TömörÃtett állomány hiba" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC hiba" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Ismeretlen hiba" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Felhasználó és csoport beállÃtás sikertelen" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: A 9666 port használatban van" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s kredit maradt" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Nem sikerÃŒlt választ kÃŒldeni." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "A CaptchaTrader hozzáférésen nincs elég credit" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Crypter lista nem található" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Crypter lista ÃŒres" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Letöltés befejezve: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Ãj CaptchaID a feltöltésbÅl: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "A Captcha 9kw.eu hozzáférésen nincs elég credit" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Scriptek telepÃtve - %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Script nem futtatható:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Hiba: %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Az ExpertDecoders hozzáférésen nincs elég credit" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "ElÅször adj meg rehost.to hozzáférést majd indÃtsd újra a pyLoad-ot." + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "ElÅször adj meg premiumize.me hozzáférést majd indÃtsd újra a pyLoad-ot." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d kredit maradt" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Captcha megfejtéshez nincs kliens csatlakozva és nincs telepÃtve Pil vagy tesseract" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Felhasználó és csoport beállÃtás sikertelen: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/hu/LC_MESSAGES/pyLoadCli.po b/locale/hu/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..bdb9441d6 --- /dev/null +++ b/locale/hu/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hungarian\n" +"Language: hu_HU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Parancssoros felÃŒlet" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s letöltés:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Sebesség: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Méret: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Befejezve: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "várakozás: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Ãllapot:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "felfÃŒggesztve" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "fut" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "össz. sebesség" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Várólistás fájlok" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Ãsszesen" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "MenÃŒ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Link hozzáadás" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Várólista kezelése" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " GyűjtÅ kezelése" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " Szerver szÃŒneteltetése/folytatása" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Szerver kilövése (Kill)" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Bezárás" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Használd a következÅ formát: add <Csomag neve> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "%d link ellenÅrzése:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "A fájl nem létezik." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad leállÃtva" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Szerver állapota" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Várólistás fájlok" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "GyűjtÅben levÅ letöltések" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Csomag várólistához adása" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Csomag gyűjtÅhöz adása" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Fájl törlése várólista/gyűjtÅ" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Csomag törlése várólista/gyűjtÅ" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Csomag áthelyezése a várólista és a gyűjtÅ között" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Fájlok újraindÃtása" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Csomagok újraindÃtása" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Online státusz ellenÅrzése, csak helyi konténer esetében" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "A konténer fájl online státuszának ellenÅrzése" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Szerver szÃŒneteltetése" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "letöltések folytatása" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "SzÃŒneteltetés/folytatás" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "szerver kilövése (Kill)" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Parancsok listája:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Nem sikerÃŒlt Ãrni a felhasználói beállÃtások fájlját" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Ehhez a pyLoad maghoz való csatlakozáshoz szÃŒkséged van py-openssl-re." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "CÃm: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Port: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Felhasználó: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Jelszó: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Hibás belépési adatok." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Nem sikerÃŒlt kapcsolódni ide: %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Ehhez a pyLoad maghoz való csatlakozáshoz szÃŒkséged van py-openssl-re." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Az interaktÃv mód néhány parancs után figyelmen kÃvÃŒl hagyva." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Csomag hozzáadása:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Add meg az új csomag nevét" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Csomag: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Hozzáadandó linkek." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Ãrd %s miután végeztél." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Link felvéve: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " vissza a fÅmenÃŒbe" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Csomagok kezelése:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Linkek kezelése:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Mit szeretnél áthelyezni?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Mit szeretnél törölni?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Mit szeretnél újraindÃtani?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Válaszd ki mit szeretnél csinálni, vagy adj meg egy csomag számot." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "törlés" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "áthelyezés" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "újraindÃtás" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - elÅzÅ" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - következÅ" + diff --git a/locale/hu/LC_MESSAGES/setup.po b/locale/hu/LC_MESSAGES/setup.po new file mode 100644 index 000000000..6e9116909 --- /dev/null +++ b/locale/hu/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Hungarian\n" +"Language: hu_HU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "i" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Ãdvözöllek a pyLoad beállÃtási segédben." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "EllenÅrizzÃŒk a rendszert és létrehozunk egy alap beállÃtást a pyLoad számára." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "A [] közötti érték minden esetben az alapértelmezett érték," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "ha nem akarod megváltoztatni, vagy nem vagy biztos benne mit válassz, csak nyomj entert." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Ne feledd: a segédhez visszatérhetsz ha a pyload.py-t a --setup vagy -s paraméterekkel indÃtod." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Ha bármi probléma lépne fel a segéd futása közben nyomj STRG-C kombinációt" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "a megszakÃtáshoz, és hogy ne induljon el újra automatikusan." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Ha készen állsz a rendszer ellenÅrzésre, nyomj Entert." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "A pyLoad futtatásához szÃŒkséged van a pycurl, sqlite és python 2.5, 2.6 vagy 2.7 verzióra." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Ezek javÃtása után futtasd újra a pyLoad-ot." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "A telepÃtÅ bezárul." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Rendszer ellenÅrzés kész, nyomj Entert az eredmény megjelenÃtéséhez." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Státusz ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "konténer dekódolás" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "ssl kapcsolat" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "automatikus captcha dekódolás" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Webes felÃŒlet" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "kiterjesztett Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "ElérhetÅ szolgáltatások:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Hiányzó szolgáltatások: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto nem elérhetÅ" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Erre szÃŒkséged van a konténer fájlok dekódolásához." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL nem elérhetÅ" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Erre szÃŒkséged van, ha biztonságos kapcsolatot szeretnél a mag vagy webes felÃŒlet eléréséhez." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Ha csak helyben akarod elérni a pyLoad-ot, az ssl nem szÃŒkséges." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "nincs elérhetÅ Captcha felismerÅ" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Csak néhány szolgáltatóhoz kell és ingyenes felhasználóként." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "GUI nem elérhetÅ" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "Grafikus felÃŒlet." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "nincs JavaScript motor" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Néhány Click'N'Load linknek szÃŒksége van erre. TelepÃtsd a Spidermonkey, ossp-js, pyv8 vagy rhino csomagokat." + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Most megszakÃthatod a telepÃtést, és kijavÃthatod az esetleges hibákat" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Folytatod a beállÃtást?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Megváltoztatod a konfigurációs fájlok helyét? A jelenlegi: %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Megváltoztatod a konfigurációs fájlok helyét?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Be akarod állÃtani a bejelentkezési adatokat és az általános beállÃtásokat?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Ajánlott az elsÅ futtatásnál." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Létre akarod hozni az általános beállÃtásokat?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Be akarod állÃtani az ssl-t?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "BeállÃtod az ssl-t?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "BeállÃtod a webes kezelÅfelÃŒletet?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "BeállÃtod a webes kezelÅfelÃŒletet?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "A beállÃtások sikeresen elvégezve." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Nyomj entert a kilépéshez majd indÃtsd újra a pyLoad-ot" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Rendszer ellenÅrz ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "A python verziód túl új. Használd a 2.6/2.7-es verziót." + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "A python verziód túl régi. Használj legalább 2.5-ös verziót." + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Python Verzió: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "A telepÃtett jinja2 verzió %s túl régi." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Biztonságosan tovább haladhatsz, de ha a webes felÃŒlet nem működik," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "frissÃtsd vagy töröld, a pyLoad tartalmaz egy alkalmas jinja2 könyvtárat." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "JS motor" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Ãltalános beállÃtások ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Ezek a belépési adatok a következÅkhöz alkalmasak: CLI, GUI, web felÃŒlet." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Felhasználónév" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "KÃŒlsÅ kliensek (GUI, CLI, ...) számára szÃŒkséges távoli elérés a hálózaton keresztÃŒli működéshez." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Ha csak a webes felÃŒletet használod, akkor kikapcsolhatod, hogy memóriát takarÃts meg." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Távoli hozzáférés engedélyezése" + +#: module/setup.py:291 +msgid "Language" +msgstr "Nyelv" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Letöltési könyvtár" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Max. egyidejű letöltés" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Ãjracsatlakozás használata?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Ãjracsatlakozó script helye" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Webes felÃŒlet BeállÃtása ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Webes felÃŒlet engedélyezése?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Figyelt cÃm, ha csak helyben akarod elérni akkor használd az 127.0.0.1 vagy localhost nevet." + +#: module/setup.py:312 +msgid "Address" +msgstr "CÃm" + +#: module/setup.py:313 +msgid "Port" +msgstr "Port" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "A pyLoad számos backend szerver lehetÅséget nyújt, ezekrÅl következik egy rövid ismertetÅ." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Használható több web-szerverrel (apache, lighttpd) egyéni beállÃtást igényel, ami nem egyszerű." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "LetölthetÅ innen: https://github.com/jonashaag/bjoern, le kell fordÃtani" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Figyelem: Néhány kivételes esetben a beépÃtett szerver nem működik megfelelÅen. Ha hibát észlel a webes felÃŒleten" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "térjen vissza ide, és válasszon másik szervert." + +#: module/setup.py:329 +msgid "Server" +msgstr "Szerver" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## SSL beállÃtás ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Futtasd ezeket a parancsokat a konfigurációs könyvtárban, az ssl tanúsÃtványok elkészÃtéséhez:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Ha kész vagy, és minden rendben, akkor aktiválhatod az ssl-t." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "SSL engedélyezése?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Válassz műveletet" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Felhasználó szerkesztés/felvétel" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Felhasználók listázása" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Felhasználó törlése" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Kilépés" + +#: module/setup.py:376 +msgid "Users" +msgstr "Felhasználók" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "A konfigurációs fájlok új helye, a jelenlegi konfiguráció nem kerÃŒl áthelyezésre." + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Konfiguráció helye" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "A konfigurációs fájlok helye megváltozott," + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Nyomj Entert a kilépéshez." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "A beállÃtások eléri útja hibás: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: hiányzik" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Jelszó: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Rövid jelszó. Legalább 4 karaktert használj." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Jelszó (ismét): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "A jelszavak nem egyeznek." + +#: module/setup.py:493 +msgid "yes" +msgstr "igen" + +#: module/setup.py:493 +msgid "true" +msgstr "igaz" + +#: module/setup.py:493 +msgid "t" +msgstr "i" + +#: module/setup.py:496 +msgid "no" +msgstr "nem" + +#: module/setup.py:496 +msgid "false" +msgstr "hamis" + +#: module/setup.py:496 +msgid "f" +msgstr "h" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Hibás érték" + diff --git a/locale/id/LC_MESSAGES/django.po b/locale/id/LC_MESSAGES/django.po new file mode 100644 index 000000000..0c654c4d7 --- /dev/null +++ b/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Indonesian\n" +"Language: id_ID\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/id/LC_MESSAGES/pyLoad.po b/locale/id/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..80b62ab74 --- /dev/null +++ b/locale/id/LC_MESSAGES/pyLoad.po @@ -0,0 +1,864 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Indonesian\n" +"Language: id_ID\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.pying failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgidmodule/threads/ServerThread.pymodule/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, p
\ No newline at end of file diff --git a/locale/id/LC_MESSAGES/pyLoadCli.po b/locale/id/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..589938d86 --- /dev/null +++ b/locale/id/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Indonesian\n" +"Language: id_ID\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/id/LC_MESSAGES/setup.po b/locale/id/LC_MESSAGES/setup.po new file mode 100644 index 000000000..7a2890016 --- /dev/null +++ b/locale/id/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Indonesian\n" +"Language: id_ID\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/it/LC_MESSAGES/django.mo b/locale/it/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index 57858c8a6..000000000 --- a/locale/it/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/it/LC_MESSAGES/django.po b/locale/it/LC_MESSAGES/django.po new file mode 100644 index 000000000..3fc6b7ee7 --- /dev/null +++ b/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Italian\n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Richiesto nuovo captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Leggi il testo nel captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyload riavviato" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "off" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Successo" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "on" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Sei sicuro di voler chiudere pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Riavvia il collegamento" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Cancella collegamento" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Immetti un nome per il pacchetto." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Clicca sulla posizione giusta del captcha." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Si Ú verificato un errore." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "La cartella Ú vuota" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Falliti" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Nessun Captcha da leggere." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Le passwords non corrispondono." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Settaggi salvati." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nuova cartella" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Sei sicuro di voler riavviare pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "attendo %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Download attivi" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Home" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "Coda" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "Collettore" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Download" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Log" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Configurazione" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Nome" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Stato" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Info" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Dimensione" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Avanzamento" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Login" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Nome utente" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Password" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Il tuo nome utente e la tua password non corrispondono. Riprova." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Per resettare i tuoi dati di accesso o aggiungere un utente esegui:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Elimina i completi" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Riavvia i falliti" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Cartella:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Password:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Modifica pacchetto" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Modifica i dettagli del pacchetto qui di seguito." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Il nome del pacchetto." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Cartella" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Nome della sottocartella per questi download." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Lista delle password usate per decomprimere." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Invia" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "reset" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Ti sei disconnesso con successo." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Percorso" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "assoluto" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativo" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "nome" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "dimensioni" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "tipo" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "ultima modifica" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "cartella superiore" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "nessun contenuto" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Generale" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Account" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Scegli una sezione dal menu" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "Premium" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Valido fino al:" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Traffico rimanente:" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Tempo" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Max paralleli" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Elimina? " + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "valido" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "non valido" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "si" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "no" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Aggiungi" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Aggiungi Account" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Inserisci i dati di un account premium per usufruire delle sue funzionalità ." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Il tuo nome utente." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "La password di questo account." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Tipo" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Scegli l'hoster per il tuo account." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Avvio" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "precedente" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "prossimo" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Fine" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Novità " + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Supporto" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Sistema" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "Python:" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "OS:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "Versione pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Cartella installazione:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Cartella configurazione:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Cartella download:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Spazio libero:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Lingua:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Porta Interfaccia Web:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Porta Interfaccia Remota:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Configurazione" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "File Manager" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Aggiungi pacchetto" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Incolla i tuoi link o carica un contenitore." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Il nome del nuovo pacchetto." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Collegamenti" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Incolla qui i tuoi link oppure qualsiasi testo e premi il pulsante filtra." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtra URL" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Password per l'archivio RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "File" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Carica un contenitore." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Destinazione" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Captcha in lettura" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "Captcha" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Il captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Testo" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Inserisci il testo per il captcha." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Chiudi" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Interfaccia web" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "Nessun aggiornamento disponibile!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugin aggiornati, per favore riavviare pyLoad." + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha in attesa" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Esci" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Amministra" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Info" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Effettua il login!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Arresto" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Annulla" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Download:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Riconnetti:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Velocità :" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Attivo:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Ricarica pagina" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "carico" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Torna in cima" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Chiudi pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Riavvia pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Per aggiungere utenti o cambiare le password usa:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Importante: l'utente Admin ha sempre tutti i permessi!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Cambia Password" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "Amministratore" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Permessi" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "cambia" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Inserisci la tua attuale e la nuova Password." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Utente" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Password attuale" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nuova password" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Inserisci la nuova password." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nuova password (ripetila)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Ripeti la nuova password." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Non hai i permessi per accedere a questa pagina." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Cartella Download non trovata." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "illimitato" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "non disponibile" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Esegui pyload.py -s per accedere al setup." + diff --git a/locale/it/LC_MESSAGES/pyLoad.mo b/locale/it/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 07b1c01c5..000000000 --- a/locale/it/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/it/LC_MESSAGES/pyLoad.po b/locale/it/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..5258f50f7 --- /dev/null +++ b/locale/it/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Italian\n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Ricevuto segnale di uscita" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad già in esecuzione con pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Impossibile cambiare il gruppo: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Impossibile cambiare utente: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "cartella dei log" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Avvio" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Uso la cartella home: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto per decodificare la libreria di file" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "cartella per i file temporanei" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "cartella dei download" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL per la connessione sicura" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Sposto la vecchia configurazione utente al DB" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Per favore controlla i tuoi dati di accesso eseguendo ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Tutti i link rimossi" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Tempo di download: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Spazio libero: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Attivazione Account..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Attivo i Plugins..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad Ú attivo e funzionante" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "riavvio pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "esco da pyLoad" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Installazione %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "%(desc)s: %(name)s non trovato" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "non posso creare %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "spegnimento..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "errore durante lo spegnimento" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyLoad chiuso da Terminale" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "Filedatabase Ú stato cancellato a causa dell'incompatibilità di versione." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Il file del database non poteva essere convertito." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Il database Ú stato convertito dalla v2 alla v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Il database Ú stato convertito dalla v3 alla v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Conversione del vecchio DB Django" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "finito" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "offiline" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "online" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "in coda" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "saltato" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "in attesa" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "temp. offline" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "avviando" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "fallito" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "annullato" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "decifrando" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "personalizzato" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "scaricando" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "elaborando" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "sconosciuto" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Pacchetto completato: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "ThriftBackend SSL in uso" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Errore backend remoto: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Avvio %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Impossibile avviare backend %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "attendo %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "Certificati SSL non trovati." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Siamo spiacenti, abbiamo abbandonato il supporto per avviare %s direttamente all'interno di pyLoad" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Puoi utilizzare il server threaded che offre buone prestazioni e l'SSL," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "naturalmente puoi continuare ad usare il tuo attuale %s con il server fastcgi di pyLoads" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "si possono trovare configurazioni di esempio nella directory module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Non Ú possibile usare %(server)s, python-flup inon Ú installato!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Errore di importazione del server lightweight: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "E' necessario scaricare e compilare bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Copia il file boern.so nella cartella module/lib oppure usa setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Naturalmente Ú necessario avere familiarità con linux e saper compilare da codice sorgente" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Il server Ú stato impostato su threaded, a causa di problemi di prestazioni noti sotto Windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Questo server non supporta SSL, si consiglia l'uso della versione threaded" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Avvio webserver integrato: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Avvio webserver SSL threaded: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Avvio Webserver threaded: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Avvio server fastcgi: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Avvio il webserver lightweight (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Non hai i permessi per accedere a questa pagina." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Cartella Download non trovata." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "illimitato" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "non disponibile" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Esegui pyload.py -s per accedere al setup." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Download accellerato fallito, ripiego su singola connessione | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Avvio Download: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Download terminato: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Il plugin %s ha fallito una funzione." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Download annullato: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Download riavviato: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Il download Ú offline: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Il download Ú temporaneamente offline: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Download fallito: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Impossibile collegarsi all'host o connessione resettata, aspetto 1 minuto e riprovo." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Download saltato: %(name)s a causa di %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Decodifica avviata: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Decodifica fallita: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Riprovo %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Recupero informazioni per %(name)s fallito | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Errore durante l'esecuzione hooks: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Attivazione di %(name)s fallita" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Plugins attivati: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Plugins disattivati: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Riconnessione fallita: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Script per la riconnessione non trovato!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Nuovo tentativo di connessione" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Fallita l'esecuzione dello script di riconnessione!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Riconnesso, nuovo IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Spazio su disco insufficiente" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Impossibile effettuare il login con l'account %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Password errata" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "Il tuo orario %s ha un formato sbagliato, usa: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "L'account %s non ha abbastanza traffico, controllo di nuovo tra 30min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "L'account %s Ú scaduto; prossimo controllo fra 1 ora" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "Limite di download raggiunto" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s ha uno schema non valido." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Errore importando %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Nessun Hoster caricato" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Attiva il download diretto sul tuo account Bitshare" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "LinkList non può essere cancellato." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Impostazioni account cancellato a causa del nuovo formato della configurazione." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Richiesta autorizzazione (nomeutente:password)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Per favore Inserisci il tuo account %s o disattiva questo plugin" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "C'era del codice HTML nel file scaricato (%s)... errore di redirect? Il download verrà riavviato." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "File temporaneamente non disponibile" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: attendo %d s tra i download." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: attendo %d s per il captcha." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "Il file scaricato era vuoto" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "Chiave API invalida" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: Traffico rimanente non sufficiente" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Traffico superato" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Traffic Share (download diretto)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Stai già scaricando da questo indirizzo IP, aspetta 60 secondi" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Auth Code non valido, il download sarà riavviato" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: Nessuno slot gratuito libero" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Hai bisogno di un account Premium per questo file" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Nome di file riportato non valido" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Errore durante il download parallelo, attendo 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Non connesso." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Decifratura non riuscita" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "Nessuna chiave fornita nell'URL" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Codice di errore:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Il file non esiste." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** I plugin sono stati aggiornati, riavvia pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Plugins aggiornati e riavviati" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Nessun aggiornamento per i plugin disponibile" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Nessun aggiornamento per pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Nuova versione di pyLoad %s disponibile ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Scaricala da qui: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Impossibile collegarsi al server per gli aggiornamenti" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nuova versione di %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Errore durante l'aggiornamento di %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "Versione non corrispondente" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Download finito: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nuova richiesta Captcha: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Rispondi usando 'c %s text on the captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "Inserire prima il tuo account premium.to e riavviare pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Aggiunto %s da HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "%s non installato" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Impossibile attivare %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Attivato" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Nessun plugin per l'estrazione attivato" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Il pacchetto %s Ú stato messo in coda per l'estrazione successiva" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Verifico pacchetto %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Estraggo in %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Nessun file trovato da estrarre" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "estrazione" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Protetto da password" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Password errata" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Cancello %s file" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Estrazione completata" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Archivio danneggiato" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC non corrispondente" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Errore Sconosciuto" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Configurazione Utente e Gruppo fallita" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: Porta 9666 già in uso" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s crediti rimasti" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Non posso inviare la risposta." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Il tuo account CaptchaTrader non ha crediti sufficienti" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Elenco Crypter non trovato" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Elenco Crypter vuoto" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Download finito: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Nuovo CaptchaID dall'upload: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Il tuo account Captcha 9kw.eu non ha abbastanza crediti" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Script installati per %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Script non eseguibile:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Errore in %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Il tuo account ExpertDecoders ha non abbastanza crediti" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Inserisci prima il tuo account rehost.to e poi riavvia pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "Inserire un account premiumize.me valido e riavviare pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d crediti rimasti" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil e tesseract non sono installati e nessun Client Ú connesso per decifrare i captcha" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Nessun risultato del captcha Ú stato trovato da alcun plugin nel tempo concesso." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Impostazione di Utente e Gruppo non riuscita: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Nessun client connesso per decifrare i captcha." + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Aggiunto pacchetto %(name)s contenente %(count)d collegamenti" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Aggiunti %(count)d link al pacchetto #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Nessun motore js rilevato, installare Spidermonkey, ossp-js, pyv8 o rhino" + diff --git a/locale/it/LC_MESSAGES/pyLoadCli.mo b/locale/it/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 158fd317a..000000000 --- a/locale/it/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/it/LC_MESSAGES/pyLoadCli.po b/locale/it/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..937056b8a --- /dev/null +++ b/locale/it/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Italian\n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Interfaccia a riga di comando" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s File Scaricati:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Velocità : " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Dimensione: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Terminato in: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "in attesa: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Stato:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "in pausa" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "in esecuzione" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "Velocità totale" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "File in coda" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Totale" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Menu:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Aggiungi Link" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "Gestisci Coda" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "Gestisci Libreria" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " Pausa/Riattiva Server" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Termina Server" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Esci" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Si prega di utilizzare questa sintassi: add <Nome pacchetto> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Controllo %d link:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Il file non esiste." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad Ú stato chiuso" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Mostra lo stato del server" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Mostra i download in coda" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Mostra i download nella libreria" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Aggiunge pacchetti alla coda" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Aggiungi pacchetto alla libreria" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Elimina file dalla Coda/Collezione" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Elimina pacchetti dalla Coda/Libreria" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Sposta Pacchetti dalla Coda alla Libreria o vice versa" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Riavvia file" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Riavvia pacchetti" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Controlla stato online, funziona con contenitori locali" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Controlla stato online di un file contenitore" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Mette in pausa il server" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "continua i download" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Commutatore pausa/riprendi" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr " termina server" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Lista dei comandi:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Impossibile scrivere il file di configurazione utente" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Hai bisogno di py-openssl per connetterti a questo pyLoad Core." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Indirizzo:" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Porta: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Nome utente: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Password:" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "I dati di login sono errati." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Impossibile stabilire una connessione a %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Hai bisogno di py-openssl per connetterti a questo pyLoad core." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Modalità interattiva ignorata dato che hai passato alcuni comandi." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Aggiungi Pacchetto:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Inserisci un nome per il nuovo pacchetto" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Pacchetto: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Analizza i link che desideri aggiungere." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Digita %s quanto hai fatto." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Link aggiunti: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " torna al menu principale" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Gestisci Pacchetti:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Gestisci Link:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Che cosa vuoi spostare?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Che cosa vuoi cancellare?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Che cosa vuoi riavviare?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Scegli cosa vuoi fare oppure digita il numero del pacchetto." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "cancella" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "sposta" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "riavvia" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - precendente" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - sucessivo" + diff --git a/locale/it/LC_MESSAGES/pyLoadGui.mo b/locale/it/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index cd1cbdf73..000000000 --- a/locale/it/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/it/LC_MESSAGES/setup.mo b/locale/it/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index e13b99bc9..000000000 --- a/locale/it/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/it/LC_MESSAGES/setup.po b/locale/it/LC_MESSAGES/setup.po new file mode 100644 index 000000000..bf61f047c --- /dev/null +++ b/locale/it/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Italian\n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "s" + +#: module/setup.py:53 +msgid "n" +msgstr "n" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Benvenuto nell'Assistente di Configurazione di pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Il setup controllerà il tuo sistema e genererà una configurazione di base per avviare pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "Il valore tra le parentesi quadre [] Ú sempre il valore di default," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "nel caso in cui non vuoi cambiare impostazione o non sei sicuro su cosa scegliere, premi semplicemente Invio." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Ricorda: Puoi sempre rieseguire questo assistente con i parametri --setup o -s, quando avvii pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Se hai qualche problema con questo assistente premi CRTL+C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "per annullare e non farlo partire più automaticamente con pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Quando sei pronto per la verifica del sistema premi Invio." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Hai bisogno di pycurl, sqlite e python 2.5, 2.6 o 2.7 per avviare pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Per favore corregilo e riavvia pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "Il setup si chiuderà ." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Verifica del sistema finita, premi Invio per vedere il report di stato." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Stato ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "decrittografia contenitore" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "connessione ssl" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "decrittografia automatica captcha" + +#: module/setup.py:104 +msgid "GUI" +msgstr "GUI" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Interfaccia web" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "Click'N'Load esteso" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "Funzioni disponibili:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Funzioni mancanti: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto non disponibile" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Hai bisofno di questo se vuoi decifrare i contenitori di file." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL non disponibile" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Questo Ú necessario se vuoi stabilire una connessione sicura con il core o l'interfaccia web." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Se vuoi accedere a pyLoad soltanto in locale, SSL non Ú necessario." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "Riconoscimento captcha non disponibile" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Necessario solo per alcuni hoster e come freeuser." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "Gui non disponibile" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "L'interfaccia utente grafica (GUI)." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "nessun motore JavaScript trovato" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Avrai bisogno di questo per alcuni link Click'N'Load. Installa Spidermonkey, ossp-js, pyv8 o rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Se vuoi puoi annullare il setup ora e correggere alcune dipendenze." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Continuare con il setup?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Vuoi cambiare il percorso per la configurazione? Quello attuale Ú %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Se si utilizza pyLoad su un server o la partizione principale si trova su una memoria flash interna potrebbe essere una buona idea cambiarla." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Cambiare il percorso della configurazione?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Si desidera configurare i dati di accesso e le impostazioni di base?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "E' consigliato per il primo avvio." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Creare configurazione di base?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Vuoi configurare l'ssl?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Configurare ssl?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Vuoi configurare l'interfaccia web?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Configurare l'interfaccia web?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Configurazione terminata con successo." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Premi Invio per uscire e riavviare pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Verifica del Sistema ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "La versione di python Ú troppo recente, usare Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "La versione di python Ú troppo vecchia, usare almeno Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Versione di Python: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "La versione installata %s di jinja2 sembra essere troppo vecchia." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Si può tranquillamente continuare, ma se l'interfaccia web non funziona," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "si prega di aggiornarla o disinstallarla, pyLoad include una libreria jinja2 sufficiente." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "motore JS" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Configurazione Base ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "I seguenti dati di accesso sono validi per CLI, GUI e interfaccia web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Nome utente" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "I client esterni (GUI, CLI o altri) richiedono accesso remoto al sistema per funzionare nella rete." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Comunque, se hai in mente di utilizzare solo l'interfaccia web puoi disattivarlo per ridurre il consumo di memoria ram." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Attiva l'accesso remoto" + +#: module/setup.py:291 +msgid "Language" +msgstr "Lingua" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Cartella di download" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Numero massimo di download paralleli" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Usare la riconnessione?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Posizione dello script di riconnessione" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Configurazione dell'interfaccia web ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Attivare l'interfaccia web?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Indirizzo di ascolto, se usi 127.0.0.1 o localhost, l'interfaccia web sarà accessibile soltanto localmente." + +#: module/setup.py:312 +msgid "Address" +msgstr "Indirizzo" + +#: module/setup.py:313 +msgid "Port" +msgstr "Porta" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad offre diversi tipi di supporto a server, segue una breve spiegazione." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Server di default, la scelta migliore se non sai quale scegliere." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Questo server supporta SSL ed Ú una valida alternativa a quello integrato." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Può essere utilizzato con apache o lighttpd, ma ne richiede la configurazione, che non Ú una procedura semplice." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Alternativa molto veloce, scritta in C, richiede libev e conoscenza di linux." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Scaricalo da qui: https://github.com/jonashaag/bjoern, compilalo" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "e copia bjoern.so in module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Attenzione: In alcuni rari casi il server integrato non funziona, se noti problemi con l'interfaccia web" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "torna qui e sostituisci il server integrato con quello threaded." + +#: module/setup.py:329 +msgid "Server" +msgstr "Server" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Configurazione SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Esegui questi comandi dalla cartella di configurazione di pyLoad per creare i certificati SSL:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Se hai finito e tutto Ú andato bene, puoi attivare SSL ora." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "Attivare SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Seleziona azione" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Crea/Modifica utente" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Lista utenti" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Rimuovi utente" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Esci" + +#: module/setup.py:376 +msgid "Users" +msgstr "Utenti" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Imposta nuovo percorso per la configurazione. La configurazione attuale NON sarà trasferita!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Percorso di configurazione" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Percorso di configurazione modificato. il setup ora si chiuderà ; riavvialo per andare avanti." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Premi Invio per uscire." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Impostazione del percorso di configurazione non riuscita: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "%s: OK" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: mancante" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Password:" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Password troppo corta. Usa almeno 4 caratteri." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Password (di nuovo): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Le passwords non corrispondono." + +#: module/setup.py:493 +msgid "yes" +msgstr "si" + +#: module/setup.py:493 +msgid "true" +msgstr "vero" + +#: module/setup.py:493 +msgid "t" +msgstr "v" + +#: module/setup.py:496 +msgid "no" +msgstr "no" + +#: module/setup.py:496 +msgid "false" +msgstr "falso" + +#: module/setup.py:496 +msgid "f" +msgstr "f" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Inserimento non valido" + diff --git a/locale/ja/LC_MESSAGES/django.po b/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 000000000..26d05ee3a --- /dev/null +++ b/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Japanese\n" +"Language: ja_JP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "æ°ãã Captcha ããªã¯ãšã¹ã" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Captcha ã®ããã¹ããèªãã§ãã ããã" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad ãåèµ·åããŸãã" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "ãªã" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "æåããŸãã" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "ãªã³" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "pyLoad ãæ¬åœã«çµäºããŸãã?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "ãªã³ã¯ãåèµ·å" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "ãªã³ã¯ãåé€" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "ããã±ãŒãžåãå
¥åããŠãã ããã" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "å³ã® captcha ã®äœçœ®ãã¯ãªãã¯ããŠãã ããã" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "ãšã©ãŒãçºçããŸããã" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "ãã©ã«ãã空ã§ã" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "èªã¿åã Captcha ããããŸããã" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "ãã¹ã¯ãŒããäžèŽããŸããã" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "èšå®ãä¿åãããŸããã" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "æ°èŠãã©ã«ã" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "pyLoad ãæ¬åœã«åèµ·åããŸãã?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "%s ãåŸ
æ©äž" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "ã¢ã¯ãã£ããªããŠã³ããŒã" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "ããŒã " + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "ãã¥ãŒ" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "ã³ã¬ã¯ã¿ãŒ" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "ããŠã³ããŒã" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "ãã°" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "èšå®" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "åå" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "ã¹ããŒã¿ã¹" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "æ
å ±" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "ãµã€ãº:" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "鲿" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "ãã°ã€ã³" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "ãŠãŒã¶ãŒå" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "ãã¹ã¯ãŒã" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "ãŠãŒã¶åããã¹ã¯ãŒããäžèŽããŸãããå詊è¡ããŠãã ããã" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "ãã°ã€ã³ ããŒã¿ããªã»ããããããŠãŒã¶ã远å ããã«ã¯ä»¥äžãå®è¡ããŠãã ãã:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "åé€ãå®äºããŸãã" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "åèµ·åã«å€±æããŸãã" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "ãã©ã«ã:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "ãã¹ã¯ãŒã:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "ããã±ãŒãžãç·šé" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "äžã®ããã±ãŒãžã®è©³çްãç·šéããŸãã" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "ããã±ãŒãžã®ååã" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "ãã©ã«ããŒ" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "ãããã®ããŠã³ããŒãã®ããã®ãµããã©ã«ãã®ååã§ãã" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "unrar ã«äœ¿ããããã¹ã¯ãŒãã®äžèЧã§ãã" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "éä¿¡" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "ãªã»ãã" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "æ£åžžã«ãã°ã¢ãŠãããŸããã" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "ãã¹" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "絶察ç" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "çžå¯Ÿç" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "åå" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "æšæ¬æ°" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "çš®é¡" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "æçµæŽæ°" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "芪ãã£ã¬ã¯ããª" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "å
容ãªã" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "æšæº" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "ãã©ã°ã€ã³" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "ã¢ã«ãŠã³ã" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "ã¡ãã¥ãŒããã»ã¯ã·ã§ã³ãéžæ" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "ãã©ã°ã€ã³" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "ãã¬ãã¢ã " + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "æå¹æé" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "æ®ããã©ãã£ãã¯" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "æé" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "æå€§ã®äžŠåæ°" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "åé€ããŸãã?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "æå¹ã§ã" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "ç¡å¹" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "ã¯ã" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "ããã" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "远å " + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "ãã¬ãã¢ã æ©èœã䜿ãã«ã¯ã¢ã«ãŠã³ã ããŒã¿ãå
¥åããŠãã ããã" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "ããªãã®ãŠãŒã¶åã§ãã" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "ãã®ã¢ã«ãŠã³ãã®ãã¹ã¯ãŒãã§ãã" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "ããªãã®ã¢ã«ãŠã³ãã®ãã¹ãã£ã³ã°äŒç€ŸãéžæããŠãã ããã" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "éå§" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "åãž" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "次ãž" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "çµäº" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "ãã¥ãŒã¹" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "ãµããŒã" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad ã®ããŒãžã§ã³:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "ã€ã³ã¹ããŒã« ãã©ã«ã:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "èšå®ãã©ã«ã:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "ããŠã³ããŒã ãã©ã«ã:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "空ãé å:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "èšèª:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "ãŠã§ãã€ã³ã¿ãã§ãŒã¹ã®ããŒã:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "ãªã¢ãŒã ã€ã³ã¿ãã§ãŒã¹ã®ããŒã:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "ãã¡ã€ã«ãããŒãžã£" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "ããã±ãŒãžã远å " + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "ãªã³ã¯ã貌ãä»ãããã³ã³ãããã¢ããããŒãããŠãã ããã" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "æ°ããããã±ãŒãžã®ååã" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "ãªã³ã¯" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "ããã«ãªã³ã¯ãä»»æã®ããã¹ãã貌ãä»ããããã£ã«ã¿ ãã¿ã³ãæŒããŠãã ããã" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "ãã£ã«ã¿ URL" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "RAR ã¢ãŒã«ã€ãã®ãã¹ã¯ãŒã" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "ãã¡ã€ã«" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "ã³ã³ãããã¢ããããŒãããŠãã ããã" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "ä¿åå
ïŒ" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Captcha ãèªã¿èŸŒã¿äž" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Captcha ã§ãã" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "ããã¹ã" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Captcha ã®ããã¹ããå
¥åããŠãã ããã" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "éãã" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "ãŠã§ãã€ã³ã¿ãã§ãŒã¹" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad ã®æŽæ°ãå©çšã§ããŸã!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "ãã©ã°ã€ã³ãæŽæ°ãããŸãããåèµ·åããŠãã ãã!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha ãåŸ
æ©äž" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "ãã°ã¢ãŠã" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "管ç" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "æ
å ±" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "ãã°ã€ã³ããŠãã ãã!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "忢" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "ãã£ã³ã»ã«" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "ããŠã³ããŒã:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "忥ç¶:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "é床:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "ã¢ã¯ãã£ã:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "ããŒãžãåèªèŸŒ" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "èªã¿èŸŒã¿äž" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "ãããã«æ»ã" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "pyLoad ãçµäº" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "pyLoad ãåèµ·å" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "ãŠãŒã¶ã远å ãŸãã¯ãã¹ã¯ãŒãã倿Žããã«ã¯:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "éèŠ: 管çè
ãŠãŒã¶ã«ã¯åžžã«ãã¹ãŠã®æš©éããããŸã!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "ãã¹ã¯ãŒãã倿Ž" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "æš©é" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "倿Ž" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "çŸåšã®ãã¹ã¯ãŒããšæ°ãããã¹ã¯ãŒããå
¥åããŠãã ããã" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "ãŠãŒã¶" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "çŸåšã®ãã¹ã¯ãŒã" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "æ°ãããã¹ã¯ãŒã" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "æ°ãããã¹ã¯ãŒãã§ãã" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "æ°ãããã¹ã¯ãŒã (åå
¥å)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "æ°ãããã¹ã¯ãŒããç¹°ãè¿ããŠãã ããã" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ç¡å¶é" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "å©çšäžå¯" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/ja/LC_MESSAGES/pyLoad.po b/locale/ja/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..45cecdb97 --- /dev/null +++ b/locale/ja/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Japanese\n" +"Language: ja_JP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "çµäºã®ã·ã°ãã«ãåä¿¡" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad ã¯ããã»ã¹ ID %s ã§æ¢ã«å®è¡äž" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "ã°ã«ãŒãã®å€æŽã«å€±æããŸãã: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "ãŠãŒã¶ãŒã®å€æŽã«å€±æããŸãã: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "ãã°ã®ãã©ã«ã" + +#: module/Core.py:340 +msgid "Starting" +msgstr "éå§äž" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "ããŒã ãã£ã¬ã¯ããªãšã㊠%s ã䜿çšäž" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "äžæãã¡ã€ã«ã®ãã©ã«ã" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "ããŠã³ããŒãå
ã®ãã©ã«ã" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "ã»ãã¥ã¢ãªæ¥ç¶ã®ããã® OpenSSL" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "./pyload.py -u ã§ããªãã®ãã°ã€ã³ããŒã¿ããã§ãã¯ããŠãã ãã" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "ãã¹ãŠã®ãªã³ã¯ãåé€ãããŸãã" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "ããŠã³ããŒãæé: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "空ãé å: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "ã¢ã«ãŠã³ããã¢ã¯ãã£ããŒãäž..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "ãã©ã°ã€ã³ãã¢ã¯ãã£ããŒãäž..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad ãå®è¡äž" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "pyLoad ãåèµ·åäž" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad ãçµäºããŸã" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "%s ãã€ã³ã¹ããŒã«" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "ã·ã£ããããŠã³äž..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "ã·ã£ããããŠã³äžã«ãšã©ãŒ" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "å®äº" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "ãªãã©ã€ã³" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "ãªã³ã©ã€ã³" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "ãã¥ãŒã«å
¥ã£ãŠããŸãã" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "ã¹ããã" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "åŸ
æ©äž" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "äžæçã«ãªãã©ã€ã³" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "éå§äž" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "倱æããŸãã" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "äžæ¢ããŸãã" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "埩å·å" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "ã«ã¹ã¿ã " + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "ããŠã³ããŒãäž" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "åŠçäž" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "äžæ" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "ããã±ãŒãžãå®äºããŸãã: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "ãªã¢ãŒã ããã¯ãšã³ã ãšã©ãŒ: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "éå§ %(name)sïŒ%(addr)sïŒ%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr " ããã¯ãšã³ã %(name)sã®èªã¿èŸŒã¿ã«å€±æãã |%(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "%s ãåŸ
æ©äž" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL èšŒææžãèŠã€ãããŸããã" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "ãã®ãµãŒããŒã§ SSL ã¯ãããŸããã代ããã«ã¹ã¬ããã䜿çšããŠãã ãã" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ç¡å¶é" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "å©çšäžå¯" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "ããŠã³ããŒã ãã£ã³ã¯ãžã®ç§»è¡ã«å€±æããŸãã 1 ã€ã®æ¥ç¶ |ã%s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "ããŠã³ããŒãéå§: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "ããŠã³ããŒãå®äº: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "ãã©ã°ã€ã³ %s ã«ã¯é¢æ°ããããŸããã" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "ããŠã³ããŒããäžæ¢: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "ããŠã³ããŒããåé: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "ããŠã³ããŒãããªãã©ã€ã³: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "ããŠã³ããŒããäžæçã«ãªãã©ã€ã³: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "ããŠã³ããŒãã«å€±æããŸãã: %(name)s|%(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "ãã¹ããŸãã¯æ¥ç¶ã®ãªã»ããã«æ¥ç¶ã§ããªãã£ãããã1 ååŸæ¥ç¶ã«å詊è¡ããŠãã ããã" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "ããŠã³ããŒããã¹ãããããŸãã:%(plugin)sã«ãã %(name)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "%(name)sã®å€±æã®æ
å ±ååŸãã |%(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "%(name)sãã¢ã¯ãã£ã ã«å€±æããŸãã" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "忥ç¶ã«å€±æããŸãã: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "忥ç¶ã¹ã¯ãªãããèŠã€ãããŸãã!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "忥ç¶ãéå§äž" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "倱æããå®è¡ã¹ã¯ãªããåæ¥ç¶ ïŒ" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "忥ç¶ãæ°ãã IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "ããã€ã¹ã«ç©ºãé åäžè¶³" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "ã¢ã«ãŠã³ã%(user)s ã§ã¯ãã°ã€ã³ã§ããŸããã§ãã |%(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "ééã£ããã¹ã¯ãŒã" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "ã¢ã«ãŠã³ã %s ãååãªãã©ãã£ãã¯ããªãã30 åã§ããäžåºŠãã§ãã¯" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "ã¢ã«ãŠã³ã %s ã¯æå¹æéãåããŠã1 h ã§ããäžåºŠãã§ãã¯" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "ããŠã³ããŒãå¶éã«éããŸãã" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "%(name)sïŒ%(msg)sã®ã€ã³ããŒã ãšã©ãŒ" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "ãã¹ãã£ã³ã° ãµãŒãã¹ãèªã¿èŸŒãŸããŠããŸãã" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Bitshare ã¢ã«ãŠã³ãã§çŽæ¥ã®ããŠã³ããŒããæå¹ã«ããŸãã" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr " (username:password)æ¿èªãå¿
èŠ" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "%S ã¢ã«ãŠã³ããå
¥åãããããã®ãã©ã°ã€ã³ãç¡å¹ã«ããŠãã ããã" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "ãã¡ã€ã«ãäžæçã«å©çšã§ããŸããã" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: ããŠã³ããŒã %d ç§éåŸ
æ©ããŠããŸãã" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: ãã£ãã㣠%d ç§ãåŸ
ã£ãŠããŸãã" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "ããŠã³ããŒããããã¡ã€ã«ã空ã ã£ã" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "API ããŒãç¡å¹ã§ãã" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%sïŒååãªãã©ãã£ãã¯ããªã" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "ãã©ãã£ãã¯ãè¶
ããŠããŸã" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "æ¥æµ: ãã©ãã£ãã¯ãå
±æ (ããŠã³ããŒãã«ããçŽè²©)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "æ¢ã«ãã® ip ã¢ãã¬ã¹ããããŠã³ããŒãããã60 ç§ãåŸ
ã£ãŠããŸãã" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "ç¡å¹ãªèªèšŒã³ãŒããããŠã³ããŒããåèµ·å" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareComïŒ ç©ºãã¹ããã" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "ãã®ãã¡ã€ã«ã®ãã¬ãã¢ã ã¢ã«ãŠã³ããå¿
èŠããããŸãã" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "ç¡å¹ãªãã¡ã€ã«åãå ±å" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "䞊åããŠã³ããŒã ãšã©ãŒã60ç§ãåŸ
ã£ãŠããŸãã" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "ãã°ã€ã³ããŠããŸããã" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "埩å·åã«å€±æããŸãã" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "URL ã§æäŸããããã¡ã€ã« ããŒããããŸããã" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "ãšã©ãŒ ã³ãŒã:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "* * * ãã©ã°ã€ã³ãæŽæ°ãããŠãpyLoad ãåèµ·åããŠãã ãã * * *" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "ãã©ã°ã€ã³ã®æŽæ°ããåèªã¿èŸŒã¿" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "ãã©ã°ã€ã³ã®æŽæ°ã¯ãããŸããã" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "PyLoad ã®æŽæ°" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "* * * æ°ãã pyLoad ããŒãžã§ã³ %s ãå©çš * * *" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "* * * ãããåŸãããã§: http://pyload.org/download * * *" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "æŽæ°ãµãŒããŒã«æ¥ç¶ããããšã¯ã§ããŸããã" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "æ°ããããŒãžã§ã³ã®%(type)s|%(name)s%(version) .2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "%sãæŽæ°ãããšãã®ãšã©ãŒ" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "ããŒãžã§ã³ã®äžäžèŽ" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "ããŠã³ããŒãå®äº: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "æ°ãããã£ããã£èŠæ±: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "'C %s ããã¹ãã®ãã£ããã£ã' ãšçã" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "HotFolder ãã%s远å " + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "%s ãã€ã³ã¹ããŒã«ãããŸãã" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "%S ãã¢ã¯ãã£ãã«ã§ããŸããã§ããã" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "ã¢ã¯ãã£ãå" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "ã¢ã¯ãã£ãåã®ãã©ã°ã€ã³ããªã" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "ããã±ãŒãž %s ã¯ãæœåºåŸã®ãã¥ãŒ" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "ããã±ãŒãž %s ããã§ãã¯" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "%S ãæœåºããŸãã" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "ãã¡ã€ã«ãæœåºãããèŠã€ãããŸãã" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "å±éäž" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "ãã¹ã¯ãŒãã§ä¿è·ãããŠããŸã" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "æ£ãããªããã¹ã¯ãŒã" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "%s åã®ãã¡ã€ã«ãåé€äž" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "å±éãå®äºããŸãã" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "ã¢ãŒã«ã€ã ãšã©ãŒ" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC ãäžäžèŽ" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "äžæãªãšã©ãŒ" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "ãŠãŒã¶ãŒèšå®ããã³ã°ã«ãŒãã«å€±æããŸãã" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: 䜿çšäžã®ããŒã 9666" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s ã®ã¯ã¬ãžãããå·Š" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "å¿çãéä¿¡ã§ããŸããã§ããã" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "ããªãã® CaptchaTrader ã¢ã«ãŠã³ããååãªã¯ã¬ãžãã" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Crypter ãªã¹ããèŠã€ãããŸãã" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Crypter ãªã¹ãã¯ç©ºã§ãã" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "ããŠã³ããŒãå®äº: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "ã¢ããããŒãããæ°ãã CaptchaID: %s: %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "ããªãã®ãã£ãã㣠9kw.eu ã¢ã«ãŠã³ããååãªã¯ã¬ãžãã" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "%s ã®ã€ã³ã¹ããŒã« ã¹ã¯ãªãã" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "ã¹ã¯ãªããããªãå®è¡å¯èœãã¡ã€ã«:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "%(script)s ã®ãšã©ãŒïŒ%(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "ããªãã® ExpertDecoders ã¢ã«ãŠã³ããååãªã¯ã¬ãžãã" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "ãŸããrehost.to ã¢ã«ãŠã³ãã远å ããpyLoad ãåèµ·åããŠãã ããã" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d ã®ã¯ã¬ãžãããæ®ã£ã" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil ãšããã»ã©ã¯ã ã€ã³ã¹ããŒã«ãããŠããªãã¯ã©ã€ã¢ã³ãæ¥ç¶ captcha è§£èª" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "ãŠãŒã¶ãŒãšã°ã«ãŒãã®èšå®ã«å€±æããŸãã: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/ja/LC_MESSAGES/pyLoadCli.po b/locale/ja/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..40b14f12c --- /dev/null +++ b/locale/ja/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Japanese\n" +"Language: ja_JP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " ã³ãã³ã ã©ã€ã³ ã€ã³ã¿ãã§ãŒã¹" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s ããŠã³ããŒã:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " é床: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " ãµã€ãº: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " å®äº: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "åŸ
æ©äž: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "ã¹ããŒã¿ã¹:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "äžæåæ¢" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "å®è¡ããŠããŸãã" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "åèšé床" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "ãã¥ãŒå
ã®ãã¡ã€ã«" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "åèš" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "ã¡ãã¥ãŒ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " ãªã³ã¯ã远å " + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " ãã¥ãŒã管ç" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " ã³ã¬ã¯ã¿ãŒã管ç" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " ãµãŒããŒãäžæåæ¢/åé" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " ãµãŒããŒãçµäºããã" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " çµäº" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "ãã®æ§æã䜿çšããŠãã ãã: add <Package name> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "%d åã®ãªã³ã¯ããã§ãã¯äž:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "ãã¡ã€ã«ãååšããŸããã" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad ãçµäºããŸãã" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "å°å·ãµãŒããŒã®ç¶æ
" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "ãã¥ãŒå
ã®ããŠã³ããŒããå°å·" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "ã³ã¬ã¯ã¿ãŒå
ã®ããŠã³ããŒããå°å·" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "ããã±ãŒãžããã¥ãŒã«è¿œå " + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "ããã±ãŒãžãã³ã¬ã¯ã¿ãŒã«è¿œå " + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "ãã¥ãŒ/ã³ã¬ã¯ã¿ãŒãããã¡ã€ã«ãåé€" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "ãã¥ãŒ/ã³ã¬ã¯ã¿ãŒããããã±ãŒãžãåé€" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "ãã¥ãŒããã³ã¬ã¯ã¿ãŒ (ãŸãã¯ãã®é) ã«ããã±ãŒãžãç§»å" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "ãã¡ã€ã«ãåèµ·å" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "ããã±ãŒãžãåèµ·å" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "ãªã³ã©ã€ã³ã®ç¶æ
ãããŒã«ã« ã³ã³ããã®ä»äºããã§ãã¯" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "ã³ã³ãã ãã¡ã€ã«ã®ãªã³ã©ã€ã³ç¶æ
ããã§ãã¯" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "ãµãŒããŒãäžæåæ¢" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "ããŠã³ããŒããç¶ç¶" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "äžæåæ¢/åéãåæ¿ã" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "ãµãŒããŒãçµäºããã" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "ã³ãã³ãã®äžèЧ:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "ãŠãŒã¶ãŒèšå®ãã¡ã€ã«ã«æžã蟌ãããšãã§ããŸããã§ãã" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "ãã® pyLoad ã³ã¢ã«æ¥ç¶ããã«ã¯ py-openssl ãå¿
èŠã§ãã" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "ã¢ãã¬ã¹: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "ããŒã: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "ãŠãŒã¶ãŒå: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "ãã¹ã¯ãŒã: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "ãã°ã€ã³ ããŒã¿ãééã£ãŠããŸãã" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "%(addr)s:%(port)s ãžã®æ¥ç¶ã確ç«ã§ããŸããã§ããã" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "ãã® pyLoad ã³ã¢ã«æ¥ç¶ããã«ã¯ py-openssl ãå¿
èŠã§ãã" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "察話ã¢ãŒãã¯ããªããå
¥åããããã€ãã®ã³ãã³ããç¡èŠããŸããã" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "ããã±ãŒãžã远å :" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "æ°ããããã±ãŒãžã®ååãå
¥å" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "ããã±ãŒãž: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "远å ããããªã³ã¯ãè§£æããŸã" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "çµãã£ãã %s ãå
¥åããŠãã ããã" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "ãªã³ã¯ã远å ãããŸãã: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " ã¡ã€ã³ ã¡ãã¥ãŒã«æ»ã" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "ããã±ãŒãžã管ç:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "ãªã³ã¯ã管ç:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "äœãç§»åããŸãã?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "äœãåé€ããŸãã?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "äœãåèµ·åããŸãã?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "äœãããããéžæãããããã±ãŒãžçªå·ãå
¥åããŠãã ããã" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "åé€" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "ç§»å" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "åèµ·å" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - å" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - 次" + diff --git a/locale/ja/LC_MESSAGES/setup.po b/locale/ja/LC_MESSAGES/setup.po new file mode 100644 index 000000000..b350f1063 --- /dev/null +++ b/locale/ja/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Japanese\n" +"Language: ja_JP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "pyLoad èšå®ã¢ã·ã¹ã¿ã³ãã«ããããã" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "ããã¯ããªãã®ã·ã¹ãã ããã§ãã¯ããåºæ¬çãªã»ããã¢ãã pyLoad ãå®è¡ããããã«ã" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "è§ãã£ãå
ã®å€ã¯åžžã«ãæ¢å®å€ã¯" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "ããã倿Žããããªããäœãéžæãã確èªãå Žåãããã ããå
¥åããŸãã" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "å¿ããŠã¯ãããªãïŒ pyload.py ãèµ·åãããšåžžã«ã»ããã¢ãããŸãã¯-s ãã©ã¡ãŒã¿ãŒã§ãã®ã¢ã·ã¹ã¿ã³ããåå®è¡ããããšãã§ããŸãã" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "äžæ¢ããªãã§ãã ãã圌ã¯ãã¯ãèªåçã« pyload.py ãéå§ãããŠãã ããã" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "ã·ã¹ãã ãã§ãã¯ã®æºåãæŽã£ãããããããå
¥åããŸãã" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "pyLoad ãå®è¡ããã«ã¯ pycurl ãš sqliteãpython 2.5 ãŸã㯠2.6ã2.7 ãå¿
èŠã§ãã" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "ãããä¿®æ£ã㊠pyLoad ãåå®è¡ããŠãã ããã" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## ç¶æ
##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "SSL æ¥ç¶" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "èªå captcha è§£èª" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "ãŠã§ãã€ã³ã¿ãã§ãŒã¹" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL ãå©çšã§ããŸãã" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "GUI ãå©çšã§ããŸãã" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "ã°ã©ãã£ã«ã« ãŠãŒã¶ ã€ã³ã¿ãŒãã§ã€ã¹ã§ãã" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "JavaScript ãšã³ãžã³ãèŠã€ãããŸãã" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "ã»ããã¢ãããç¶ããŸããã" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "èšå®ãã¹ã倿ŽããŸãããçŸåšã¯ %s ã§ãã" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "èšå®ãã¹ã®å€æŽã§ããïŒ" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "ãã°ã€ã³ ããŒã¿ãšåºæ¬èšå®ãæ§æããŸããã" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "æåã®å®è¡ããå§ãããŸãã§ãã" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "åºæ¬çãªã»ããã¢ãããè¡ããïŒ" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Ssl ãæ§æããŸããã" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Ssl ãæ§æããŸããã" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "ãŠã§ãã€ã³ã¿ ãã§ãŒã¹ãæ§æããŸããã" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "ãŠã§ãã€ã³ã¿ ãã§ãŒã¹ãæ§æããŸããã" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "ã»ããã¢ããã¯æ£åžžã«å®äºããŸããã" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "PyLoad ãåèµ·åãçµäºãå
¥åããã" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## ã·ã¹ãã ãã§ã㯠##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Python ã®ããŒãžã§ã³: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "JS ãšã³ãžã³" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## åºæ¬çãªã»ããã¢ãã ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "次㮠logindata 㯠CLI ãš GUI ã®ãŠã§ãã€ã³ã¿ ãã§ãŒã¹ã«æå¹ã§ãã" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "ãŠãŒã¶ãŒå" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "èšèª" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "ããŠã³ããŒããã©ã«ã" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "æå€§äžŠåããŠã³ããŒã" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "忥ç¶ã䜿çšããŸãã" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "ã¹ã¯ãªããã®å Žæãæ¥ç¶ãçŽããŸã" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## ãŠã§ãã€ã³ã¿ãã§ãŒã¹ã®ã»ããã¢ãã ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "ãŠã§ãã€ã³ã¿ãã§ãŒã¹ãã¢ã¯ãã£ããŒãããŸãã?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "ãªã¹ã³ ã¢ãã¬ã¹ã127.0.0.1 ãŸã㯠localhostããŠã§ãã€ã³ã¿ ãã§ãŒã¹ã䜿çšããå Žåã¯ãããŒã«ã«ã§ã®ã¿ã¢ã¯ã»ã¹å¯èœã" + +#: module/setup.py:312 +msgid "Address" +msgstr "ã¢ãã¬ã¹" + +#: module/setup.py:313 +msgid "Port" +msgstr "ããŒã" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad ä»ãç°¡åãªèª¬æã次ã®ããã€ãã®ãµãŒã㌠ããã¯ãšã³ããæäŸããŠããŸãã" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Apacheãlighttpd ã䜿çšããããšãã§ããŸããããŸãã«ãç°¡åãªä»äºã§ã¯ãªããããããæ§æããå¿
èŠããããŸãã" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "ãããããããåŸã: https://github.com/jonashaag/bjoernããããã³ã³ãã€ã«" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "泚æ: ããã€ãã®ãŸããªã±ãŒã¹ã§ãçµã¿èŸŒã¿ã®ãµãŒããŒãåäœããªãããŠã§ãã€ã³ã¿ ãã§ãŒã¹ã§åé¡ãçºçããå Žå" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "ããã«æ»ã£ãŠããããããã§ã¹ã¬ããã«çµã¿èŸŒã¿ãµãŒããŒã倿ŽããŸãã" + +#: module/setup.py:329 +msgid "Server" +msgstr "ãµãŒããŒ" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## SSL ã»ããã¢ãã ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Ssl èšŒææžã pyLoad config ãã©ã«ããŒãããããã®ã³ãã³ããå®è¡ããŸãã" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "å®äºãããããã¹ãŠãããŸãè¡ã£ãå Žå ssl ãä»ããã¢ã¯ãã£ãåããããšãã§ããŸãã" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "SSL ãæå¹ã«ãããïŒ" + +#: module/setup.py:360 +msgid "Select action" +msgstr "åäœãéžæ" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - ãŠãŒã¶ãäœæ/ç·šé" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - ãŠãŒã¶äžèЧã衚瀺" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - ãŠãŒã¶ãåé€" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - çµäº" + +#: module/setup.py:376 +msgid "Users" +msgstr "ãŠãŒã¶ãŒ" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "èšå®ãã¹" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "çµäºããã«ã¯ Enter ãæŒããŠãã ããã" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "èšå®ãã¹ã®èšå®ã«å€±æããŸãã: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: ãããŸãã" + +#: module/setup.py:464 +msgid "Password: " +msgstr "ãã¹ã¯ãŒã: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "ãã¹ã¯ãŒããçãããŸãã4 æå以äžã«ããŠãã ããã" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "ãã¹ã¯ãŒã (åå
¥å): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "ãã¹ã¯ãŒããäžèŽããŸããã" + +#: module/setup.py:493 +msgid "yes" +msgstr "ã¯ã" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "ããã" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "ç¡å¹ãªå
¥å" + diff --git a/locale/ko/LC_MESSAGES/django.po b/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 000000000..93877fc34 --- /dev/null +++ b/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Korean\n" +"Language: ko_KR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/ko/LC_MESSAGES/pyLoad.po b/locale/ko/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..048520190 --- /dev/null +++ b/locale/ko/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Korean\n" +"Language: ko_KR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/ko/LC_MESSAGES/pyLoadCli.po b/locale/ko/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..e85c7fb29 --- /dev/null +++ b/locale/ko/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Korean\n" +"Language: ko_KR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/ko/LC_MESSAGES/setup.po b/locale/ko/LC_MESSAGES/setup.po new file mode 100644 index 000000000..38f52ea3d --- /dev/null +++ b/locale/ko/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Korean\n" +"Language: ko_KR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/ms/LC_MESSAGES/django.po b/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 000000000..258e0cdf8 --- /dev/null +++ b/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Malay\n" +"Language: ms_MY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Gagal" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Jenis" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Sistem" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Persediaan" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/ms/LC_MESSAGES/pyLoad.po b/locale/ms/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..4d92823a5 --- /dev/null +++ b/locale/ms/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Malay\n" +"Language: ms_MY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/ms/LC_MESSAGES/pyLoadCli.po b/locale/ms/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..d4119d884 --- /dev/null +++ b/locale/ms/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Malay\n" +"Language: ms_MY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Tambah pakej:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Masukkan nama untuk pakej baru" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Pakej: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Pautan ditambah: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " kembali ke menu utama" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Menguruskan pakej:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Menguruskan pautan:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Apakah yang anda ingin mengalih?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Apakah yang anda ingin hapuskan?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Apakah yang anda ingin memulakan semula?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "hapuskan" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "mengalih" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/ms/LC_MESSAGES/setup.po b/locale/ms/LC_MESSAGES/setup.po new file mode 100644 index 000000000..837f7ed34 --- /dev/null +++ b/locale/ms/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Malay\n" +"Language: ms_MY\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/nl/LC_MESSAGES/django.mo b/locale/nl/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index bea13751c..000000000 --- a/locale/nl/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/nl/LC_MESSAGES/django.po b/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 000000000..912576e9e --- /dev/null +++ b/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Dutch\n" +"Language: nl_NL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Nieuw Captcha verzoek" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Lees de tekst van de captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "PyLoad is herstart" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "uit" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Succes" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "aan" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Ben je zeker dat je pyLoad wilt afsluiten?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Herstart Link" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Verwijder Link" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Geef een naam voor het pakket op." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Gelieve op de correcte captcha positie te klikken." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Fout opgetreden." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Map is leeg" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Mislukt" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Geen captchas beschikbaar." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Wachtwoorden kwamen niet overeen." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Instellingen bewaard." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nieuwe map" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Ben je zeker dat je pyLoad wilt herstarten?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "wachtend %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Actieve downloads" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Configuratie" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Naam" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Status" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Informatie" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Grootte" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Vooruitgang" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Inloggen" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Gebruikersnaam" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Wachtwoord" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Gebruikersnaam en wachtwoord komen niet overeen, probeer nogmaals." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Om logindata te resetten of gebruiker toe te voegen start:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Verwijder voltooide" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Herstart gefaalde" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Map:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Wachtwoord:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Pakket bewerken" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Bewerk de pakketdetails hieronder." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "De naam van het pakket." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Map" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Naam van de submap voor deze downloads." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Lijst van wachtwoorden die voor het uitpakken gebruikt worden." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Verzenden" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Wissen" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Je bent succesvol uitgelogd." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Pad" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absoluut" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relatief" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "naam" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "grootte" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "laatst gewijzigd" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "bovenliggende map" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "geen inhoud" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Algemeen" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Accounts" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Kies een categorie uit het menu" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Geldig tot" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Resterend volume" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Tijd" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Verwijderen?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "geldig" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "ongeldig" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "ja" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "nee" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Toevoegen" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Voeg Account toe" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Vul accountgegevens in om premium functies te gebruiken." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Gebruikersnaam." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Het wachtwoord voor deze account." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Kies de hoster voor je account." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "vorige" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "volgende" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Einde" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Nieuws" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Ondersteuning" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Systeem" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad versie:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Installatie Map:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Configuratie Map:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Download Map:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Beschikbare Ruimte:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Taal:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Webinterface Poort:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Remote Interface Poort:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Installatie" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Bestandsbeheer" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Pakket Toevoegen" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Plak je links of upload een dlc bestand." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "De naam van het nieuwe pakket." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Plak je links of tekst hier en druk op de filterknop." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Wachtwoorden voor RAR-archieven" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Bestand" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Upload een container." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Bestemming" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Captcha's lezen" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "De captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Tekst" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Typ de tekst van de captcha in." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Sluiten" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad Update beschikbaar!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins updated, herstart pyLoad!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha's beschikbaar" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Afmelden" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administratie" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Informatie" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Gelieve aan te melden!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Annuleren" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Snelheid:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Actief:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Herlaad pagina" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "laden" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Naar top" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Sluit pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Herstart pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Toevoegen van gebruiker of wijzigen wachtwoord gebruik:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Belangrijk: Administrator heeft altijd alle toegangsrechten!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Wachtwoord Wijzigen" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Toegangsrechten" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "wijzigen" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Vul je huidig en gewenste wachtwoord in." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Gebruiker" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Huidig wachtwoord" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nieuw wachtwoord" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Nieuw wachtwoord." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nieuw wachtwoord (herhalen)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Herhaal het nieuwe wachtwoord." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Je hebt geen rechten deze pagina te bezoeken." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Downloadmap niet gevonden." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "onbeperkt" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "niet beschikbaar" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Start pyload.py -s om setup te starten." + diff --git a/locale/nl/LC_MESSAGES/pyLoad.mo b/locale/nl/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 7c52dee71..000000000 --- a/locale/nl/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/nl/LC_MESSAGES/pyLoad.po b/locale/nl/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..4f1fa4663 --- /dev/null +++ b/locale/nl/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Dutch\n" +"Language: nl_NL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Quit signaal ontvangen" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad is al actief met pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Veranderen van groep mislukt: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Veranderen van gebruiker mislukt: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "map voor logs" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Startend" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Gebruik hoofdmap: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "Container bestanden decoderen met pycrypto" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "map voor tijdelijke bestanden" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "map voor downloads" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL voor beveiligde verbinding" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Oude configuratie naar DB verplaatsen" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Controleer je logingegevens met ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Alle links verwijderd" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Downloadtijd: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Beschikbare ruimte: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Accounts worden geactiveerd..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Plugins aan het activeren..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad is lopende" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "pyLoad wordt herstart" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad wordt afgesloten" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Installeren %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "Niet te vinden %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "Niet aan te maken %(desc)s : %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "afsluiten..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "fout tijdens afsluiten" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyLoad is afgesloten via Terminal" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "Bestandsdatabase is verwijderd vanwege niet verenigbare versie." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Bestandsdatabase kan NIET geconverteerd worden." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Database is geconverteerd van v2 naar v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Database is geconverteerd van v3 naar v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Oude Django DB omzetten" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "compleet" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "in wachtrij" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "overgeslagen" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "wachtend" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "tijdelijk offline" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "startend" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "mislukt" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "afgebroken" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "decrypten" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "gepersonaliseerd" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "wordt gedownload" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "verwerken" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "onbekend" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Pakket compleet: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "SSL ThriftBackend gebruiken" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Remotebackendfout: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Opstarten %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Laden van backend %(name)s | %(error)s mislukt" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "wachtend %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL certificaten niet gevonden." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Sorry, we hebben ondersteuning voor starten van %s vanuit pyLoad verwijderd" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Je kan de threaded server gebruiken welke goede prestaties en ssl biedt," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "ook kan je de pyLoads fastcgi server gebruiken met je bestaande %s" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "voorbeeldconfiguratie is te vinden in module/webui/servers map" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Kan %(server)s niet gebruiken, python-flup is niet geinstalleerd!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Fout bij importeren lichtgewicht server: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "Je moet bjoern downloaden en compileren, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Kopieer de boern.so naar module/lib map en gebruik setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Hiervoor is kennis van linux en compileren van software een vereiste" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Server op threated gezet, vanwege bekende prestatie problemen op windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Deze server heeft geen SSL, overweeg de threaded server te gebruiken" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Opstarten van builltin webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Opstarten van threaded SSL webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Opstarten van threaded webserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Opstarten van fastcgi server: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Opstarten van lichtgewicht webserver (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Je hebt geen rechten deze pagina te bezoeken." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Downloadmap niet gevonden." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "onbeperkt" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "niet beschikbaar" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Start pyload.py -s om setup te starten." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Downloaden in chunks is mislukt, val terug op één connectie | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Download gestart: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Download compleet: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Plugin %s mist een functie." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Download afgebroken: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Download herstart: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "%s offline" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Download is tijdelijk offline: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Download mislukt: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Kan geen verbinding maken met host, wacht 1 minuut en probeer opnieuw." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Download overgeslagen: %(name)s vanwege %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Decrypten gestart: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Decrypten mislukt: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Opnieuw proberen %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Informatie verzamelen voor %(name)s mislukt | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "Uitvoeren van hooks mislukt: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Activeren mislukt van %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Geactiveerde plugins: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Niet geactiveerde plugins: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Opnieuw verbinden mislukt: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Opnieuw verbinden script niet gevonden!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Opnieuw aan het verbinden" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Uitvoeren van opnieuw verbinden script mislukt!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Opnieuw verbonden, nieuwe IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Onvoldoende schijfruimte vrij" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Kan niet inloggen onder gebruikersnaam %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Verkeerd wachtwoord opgegeven" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "Tijd %s heeft verkeerde , gebruik: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "Account %s heeft niet genoeg credits, wij proberen het opnieuw in 30min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "Account %s is verlopen, opnieuw te controleren in 1h" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "Downloadlimiet bereikt" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s heeft een ongeldig patroon." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Fout bij importeren %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Geen Hoster geladen" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Activeer Direct Downloaden in je Bitshare Account" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "LinkList kon niet gewist worden." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Accountgegevens verwijderd, vanwege nieuw configutatie formaat." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Autorisatie vereist (gebruikersnaam:wachtwoord)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Voer hier uw %s gegevens in of deactiveer deze plugin" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "Tijdens het proberen van het ophalen van het volgende bestand (%s) is er een html/pagina reactie teruggekomen, dit kan een doorsturing zijn naar een andere pagina. pyLoad zal nu opnieuw het bestand proberen binnen te halen." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Bestand tijdelijk niet beschikbaar" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: wachten tussen downloads %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: Wachten tot captcha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "Downloadlink heeft geen bestand gekoppeld" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "API sleutel ongeldig" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: Overdracht limiet bijna bereikt , niet voldoende credits" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Dataverkeer overschreden" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Bandbreedte Delen (Direct Downloaden)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Er wordt al een bestand gedownload vanaf dit ip adres, na 60 seconden volgende poging" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Ongeldige Auth Code, download wordt automatisch herstart" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: Geen beschikbaarde downloadslots" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "U heeft een premium account nodig voor deze bestand" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Bestandsnaam geeft ongeldigheidsmelding" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Gelijktijdige download mislukt, wacht 60 seconden voor volgende poging." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Niet ingelogd." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Ontcijferen van codering mislukt" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "Geen bestandssleutel meegeleverd door URL" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Foutmeldingscode:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Bestand bestaat niet." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Plugins zijn bijgewerkt, pyLoad opnieuw starten aub***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Plugins bijgewerkt en opnieuw geladen" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Geen plugin updates beschikbaar" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Geen Updates voor pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Nieuwe pyLoad Versie %s beschikbaar ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Download hier: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Niet in staat te verbinden met server voor updates" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nieuwe versie van %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Fout tijdens updaten van %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "Versie mismatch" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Download compleet: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nieuw Captcha verzoek: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Beantwoord met 'c%s text on the captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Toegevoegde %s van HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "Niet %s geinstalleerd" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Kan %s niet activeren" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Geactiveerd" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Geen uitpak plug-ins geactiveerd" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Pakket %s in wachtrij voor later uitpakken" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Controleer pakket %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Uitpakken naar %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Geen bestanden gevonden om uit te pakken" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "uitpakken" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Beveiligd met een wachtwoord" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Verkeerd wachtwoord" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "%s bestanden verwijderen" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Uitpakken voltooid" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Archief fout" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC foutief" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Onbekende fout" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Instellen van gebruikers en de groep is mislukt" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: Poort 9666 al in gebruik" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s credits over" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Kan het antwoord niet verzenden." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Uw CaptchaTrader Account heeft niet genoeg credits" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Crypter lijst niet gevonden" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Crypter lijst is leeg" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Download compleet: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Nieuwe CaptchaID van upload: %s: %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Uw Captcha 9kw.eu Account heeft niet genoeg credits" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Geïnstalleerde scripts voor %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Script niet uitvoerbaar:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Fout in %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Uw ExpertDecoders Account heeft niet genoeg credits" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Gelieve eerst uw premium account toe te voegen en daarna pyLoad te herstarten" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "uw resterende aantal credits : %d" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Captcha ontcijfering niet mogelijk : A. Client is niet verbonden & B. Pil en Tesseract module niet gevonden" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Geen captcha resultaat ontvangen in aangegeven tijd bij een van de plugins." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Instellingen van gebruiker en groep kunnen niet geladen worden : %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Geen verbinding met client om captcha te decrypten" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Pakket %(name)s toevoegen met %(count)d links" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "%(count)d links toevoegen aan pakket #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Geen js engine gedetecteerd, installeer Spidermonkey, ossp-js, pyv8 of rhino" + diff --git a/locale/nl/LC_MESSAGES/pyLoadCli.mo b/locale/nl/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index c414cfea4..000000000 --- a/locale/nl/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/nl/LC_MESSAGES/pyLoadCli.po b/locale/nl/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..35e9d3aac --- /dev/null +++ b/locale/nl/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Dutch\n" +"Language: nl_NL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Opdrachtprompt" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Snelheid: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Grootte: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Compleet in: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "wachtend: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "gepauzeerd" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "lopend" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "totale Snelheid" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Bestanden in wachtrij" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Totaal" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Links toevoegen" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "Wachtrij beheren" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "Verzamelaar beheren" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " (De)Pauzeren Server" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Server afsluiten" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Afsluiten" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Gebruik deze opbouw: add <Package name> <link> <link2> enz" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Controleren van %d links:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Bestand bestaat niet." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad was afgesloten" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Server status weergeven" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Downloads in wachtrij weergeven" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Downloads in verzamelaar weergeven" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Pakketten toevoegen aan wachtrij" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Pakket toevoegen aan verzamelaar" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Bestanden verwijderen uit Wachtrij/Verzamelaar" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Pakketten verwijderen uit Wachtrij/Verzamelaar" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Verplaats pakketten van Wachtrij naar Verzamelaar of omgekeerd" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Bestanden herstarten" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Pakketten herstarten" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Controleer online status, werkt met lokale container" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Controleert de online status van een container bestand" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Server pauzeren" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "downloads hervatten" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Pauzeren/Starten" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "server afsluiten" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Lijst met commands:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Kan configuratiebestand voor gebruiker niet aanmaken" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Om verbinding te maken met deze pyLoad Core is py-openssl nodig." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adres: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Poort: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Gebruikersnaam: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Wachtwoord: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Login gegevens verkeerd." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Kan geen verbinding maken met %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Om verbinding te maken met pyLoad is py-openssl noodzakelijk." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Interactieve modus wordt genegeerd, omdat je commando's hebt ingevult." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Pakket toevoegen:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Naam invullen voor nieuw pakket" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Pakket: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Parse de links die je wilt toevoegen." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Type %s als het klaar is." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Toegevoegde links: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " terug naar hoofdmenu" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Pakketten beheren:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Links beheren:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Wat wil je verplaatsen?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Wat wil je verwijderen?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Wat wil je herstarten?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Kies wat je wilt doen of vul pakketnummer in." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "verwijderen" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "verplaatsen" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "herstarten" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - vorige" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - volgende" + diff --git a/locale/nl/LC_MESSAGES/pyLoadGui.mo b/locale/nl/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 8bbc9385f..000000000 --- a/locale/nl/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/nl/LC_MESSAGES/setup.mo b/locale/nl/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index 8d8fd0d4f..000000000 --- a/locale/nl/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/nl/LC_MESSAGES/setup.po b/locale/nl/LC_MESSAGES/setup.po new file mode 100644 index 000000000..ed88ba315 --- /dev/null +++ b/locale/nl/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Dutch\n" +"Language: nl_NL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "j" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Welkom bij de pyLoad configuratie assistent." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Deze zal uw systeem controleren en de basissetup uitvoeren." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "De waarden tussen de haakjes [] zijn de standaardwaarden," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "mocht het zo zijn dat u deze niet wil veranderen of indien u niet zeker bent, druk op enter." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Let op: u kunt altijd deze setup herstarten met de --setup of -s parameter als u pyload.py start." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Mocht u problemen hebben met deze assistent druk op STRG-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "om af te sluiten en de assistent niet meer automatisch te starten." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Als u klaar bent voor de systeemcontrole, druk op enter." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "U heeft pycurl, sqlite en python 2.5, 2.6 of 2.7 nodig om pyLoad te starten." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Corrigeer dit en herstart pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "De setup zal nu afbreken." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Systeemcontrole is uitgevoerd, druk op enter om het statusbericht te zien." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "ssl verbinding" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "automatische captcha ontcijfering" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "uitgebreide Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "Functies beschikbaar:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Missende functies: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "geen py-crypto beschikbaar" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "U heeft dat nodig om container bestanden te openen." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "geen SSL beschikbaar" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Dit is nodig om een beveiligde verbinding in te stellen naar de core of de webinterface." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Als u pyLoad enkel lokaal gebruikt is SSL overbodig." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "geen captcha herkenning beschikbaar" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Wordt alleen gebruikt bij enkele hosters als freeuser." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "GUI niet beschikbaar" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "De grafische gebruikersomgeving." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "geen JavaScript engine gevonden" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "U heeft dit nodig voor bepaalde Click'N'Load links. Instaleer Spidermoney, ossp-js, pyv8 of rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "U kunt nu setup afbreken en enkele afhankelijkheden installeren als u dat wilt." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Doorgaan met setup?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Wilt u de configuratiemap aanpassen? Huidige is %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Als u pyLoad op een server gebruikt of de home partitie bevindt zich op intern flash-geheugen, is het een goed idee om het te veranderen." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Verander configmap?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Wilt u login gegevens en basisinstellingen configureren?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Dit is aan te raden bij een eerste start." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Basissetup creëren?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Wilt u SSL configureren?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "SSL configureren?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Wilt u de webinterface configureren?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Webinterface configureren?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Setup is succesvol voltooid." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Druk op enter om af te sluiten en start pyLoad opnieuw" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Syteemcontrole ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Uw python versie is te nieuw, gebruik python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Uw python versie is te oud, gebruik minstens python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Python versie: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Uw gestalleerde versie %s van jinja2 is te oud." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "U kan veilig verder, alleen de webinterface zal niet werken." + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "Upgrade of verwijder het, pyLoad komt zelf met een goede jinja2 versie." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Basisinstellingen ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "De volgende logingegevens zijn geldig voor CLI, GUI en webinterface." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Gebruikersnaam" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Externe cliënten (GUI, CLI of andere) hebben externe toegang nodig om te werken over het netwerk." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Als je enkel de webinterface wil gebruiken mag je het uitschakelen om RAM te besparen." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Externe toegang inschakelen" + +#: module/setup.py:291 +msgid "Language" +msgstr "Taal" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Downloadmap" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Maximale parallele downloads" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Gebruik reconnect?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Reconnect script pad" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Webinterface setup ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Activeer webinterface?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Listen adres, als u 127.0.0.1 of localhost gebruikt is de webinterface alleen lokaal beschikbaar." + +#: module/setup.py:312 +msgid "Address" +msgstr "Adres" + +#: module/setup.py:313 +msgid "Port" +msgstr "Poort" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad beschikt over een aantal server backends, nu volgt een korte uitleg." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Standaard server, de beste keuze als je niet weet welke je moet kiezen." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Deze server beschikt over SSL en is een goed alternatief voor de interne server." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Kan gebruikt worden door apache, lighttpd, vereist configuratie wat niet makkelijk te doen is." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Super snel alternatief geschreven in C, vereist verstand van libev en linux." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Download het hier: https://github.com/jonashaag/bjoern, compile het" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "en kopieer bjoern.so naar modele/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Opgelet: In sommige gevallen werkt de builtin server niet, als je problemen hebt met de webinterface." + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "kom terug en verander de builtin server naar de threaded server." + +#: module/setup.py:329 +msgid "Server" +msgstr "Server" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## SSL setup ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Voer de volgende commando's uit vanuit pyLoad configuratiemap om ssl certificaten te maken:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Als de commando's succesvol uitgevoerd zijn kunt u SSL nu activeren." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "SSL activeren?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Aktie selecteren" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Aanmaken/wijzigen gebruiker" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Lijst met gebruikers" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Gebruiker verwijderen" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Afsluiten" + +#: module/setup.py:376 +msgid "Users" +msgstr "Gebruikers" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Nieuwe configuratiemap wordt ingesteld, uw huidige configuratie wordt niet overgenomen!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Configuratiepad" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Configuratiepad is veranderd en setup zal nu afsluiten, herstart setup om verder te gaan." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Druk op enter om af te sluiten." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Instellen van configuratiepad mislukt: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: mist" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Wachtwoord: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Wachtwoord te kort. Gebruik ten minste 4 symbolen." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Wachtwoord (nogmaals): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Wachtwoorden kwamen niet overeen." + +#: module/setup.py:493 +msgid "yes" +msgstr "ja" + +#: module/setup.py:493 +msgid "true" +msgstr "waar" + +#: module/setup.py:493 +msgid "t" +msgstr "w" + +#: module/setup.py:496 +msgid "no" +msgstr "nee" + +#: module/setup.py:496 +msgid "false" +msgstr "niet waar" + +#: module/setup.py:496 +msgid "f" +msgstr "nw" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Ongeldige invoer" + diff --git a/locale/no/LC_MESSAGES/django.po b/locale/no/LC_MESSAGES/django.po new file mode 100644 index 000000000..069e9851e --- /dev/null +++ b/locale/no/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Norwegian\n" +"Language: no_NO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/no/LC_MESSAGES/pyLoad.po b/locale/no/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..4301f0e07 --- /dev/null +++ b/locale/no/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Norwegian\n" +"Language: no_NO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/no/LC_MESSAGES/pyLoadCli.po b/locale/no/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..6853d47a2 --- /dev/null +++ b/locale/no/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Norwegian\n" +"Language: no_NO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/no/LC_MESSAGES/setup.po b/locale/no/LC_MESSAGES/setup.po new file mode 100644 index 000000000..1d3d4bd71 --- /dev/null +++ b/locale/no/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Norwegian\n" +"Language: no_NO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/pa/LC_MESSAGES/django.po b/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 000000000..8b2152180 --- /dev/null +++ b/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Punjabi\n" +"Language: pa_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/pa/LC_MESSAGES/pyLoad.po b/locale/pa/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..34a0719a1 --- /dev/null +++ b/locale/pa/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Punjabi\n" +"Language: pa_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/pa/LC_MESSAGES/pyLoadCli.po b/locale/pa/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..2c76600d5 --- /dev/null +++ b/locale/pa/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Punjabi\n" +"Language: pa_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/pa/LC_MESSAGES/setup.po b/locale/pa/LC_MESSAGES/setup.po new file mode 100644 index 000000000..bc7f27197 --- /dev/null +++ b/locale/pa/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Punjabi\n" +"Language: pa_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/pl/LC_MESSAGES/django.mo b/locale/pl/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index fae662552..000000000 --- a/locale/pl/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/pl/LC_MESSAGES/django.po b/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 000000000..cbcf51c8d --- /dev/null +++ b/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Polish\n" +"Language: pl_PL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Nowy obrazek (captcha)" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "ProszÄ przeczytaÄ tekst z obrazka." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad zrestartowano" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "WyÅ" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Powodzenie" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "WÅ" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Na pewno chcesz zamknÄ
Ä" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Zrestartuj link" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "UsuÅ link" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Podaj nazwÄ paczki" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "ProszÄ kliknij na prawej stronie obrazka" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "bÅÄ
d" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Folder jest pusty" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Niepowodzenie" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Brak obrazków (captcha) do odczytania." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "HasÅo nie pasuje" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Ustawienia zapisano" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nowy folder" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Czy chcesz zrestartowaÄ pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "czekaj %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Obecnie pobierane" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "Pobrane" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Logi" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Konfiguracja" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Nazwa" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Status" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Informacja" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Rozmiar" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "PostÄp" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Logowanie" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Nazwa uÅŒytkownika" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "HasÅo" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "NieprawidÅowa nazwa uÅŒytkownika lub hasÅo. ProszÄ spróbowaÄ ponownie." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Aby zresetowaÄ dane logowania lub dodaÄ uÅŒytkownika uruchom komendÄ:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "UsuÅ zakoÅczone" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Nieudany restart" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Katalog:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "HasÅo:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Edytuj paczkÄ" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Tutaj edytuj szczegóÅy paczki." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Nazwa paczki." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Folder" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Nazwa podfolderu dla wskazanych pobraÅ." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Lista haseÅ uÅŒywanych do rozpakowywania." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "WyÅlij" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Resetuj" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Wylogowano pomyÅlnie." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "ÅcieÅŒka" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "bezpoÅrednia" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "wzglÄdna" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "nazwa" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "rozmiar" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "rodzaj" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "ostatnio zmodyfikowany" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "katalog gÅówny" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "brak treÅci" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Ogólne" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Wtyczki" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Konta" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Wybierz sekcjÄ z menu" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "WaÅŒne do" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "PozostaÅy transfer" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Czas" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Maksymalnie jednoczesnych pobraÅ" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "SkasowaÄ?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "WaÅŒny" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "nie waÅŒny" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "tak" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "nie" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Dodaj" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Dodaj konto" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Podaj swoje dane konta do korzystania z funkcji premium." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Nazwa uÅŒytkownika." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "HasÅo dla tego konta." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Typ" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Wybierz hosting dla Twojego konta." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Uruchom" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "poprzedni" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "nastÄpny" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Koniec" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "WiadomoÅci" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Wsparcie" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "System operacyjny:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "Wersja pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Folder instalacji:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Folder konfiguracji:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Folder pobierania:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Wolne Miejsce:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "JÄzyk:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Port interfejsu web:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Port interfejsu zdalnego:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Ustawienia" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "MenedÅŒer plików" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Dodaj paczkÄ" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Wklej linki lub wczytaj kontener." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Nazwa nowej paczki." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Linki" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Tutaj wklej linki lub dowolny tekst i wciÅnij przycisk filtra." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtruj adresy url" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "HasÅo do archiwum RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Plik" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Wczytaj kontener." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Miejsce docelowe" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Odczyt captcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "Captcha (obrazek)" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Tekst" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Wprowadź tekst z obrazka (captcha)." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Zamknij" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Interfejs Web" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "DostÄpna aktualizacja dla pyLoad'a!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Wtyczki zaktualizowane, zrestartuj program!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Oczekiwanie na captcha" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Wyloguj" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "ZarzÄ
dzaj" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Informacje" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Zaloguj siÄ!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Zatrzymaj" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Anuluj" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "Pobrane:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "PoÅÄ
cz ponownie:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "PrÄdkoÅÄ:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Aktywny:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "OdÅwieÅŒ stronÄ" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "wczytywanie" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Powrót na poczÄ
tek strony" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Zamknij pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Zrestartuj pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Aby dodaÄ uÅŒytkownika lub zmieniÄ hasÅo uÅŒyj:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Uwaga: Administrator ma zawsze wszystkie prawa!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Zmiana HasÅa" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "Administrator" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Uprawnienia" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "zmieÅ" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Wprowadź swoje hasÅo" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "UÅŒytkownik" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Aktualne hasÅo" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nowe hasÅo" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Nowe hasÅo." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nowe hasÅo (powtórz)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "ProszÄ powtórzyÄ nowe hasÅo." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Nie posiadasz uprawnieÅ dostÄpu do tej strony." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Nie znaleziono katalogu pobierania." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "Bez limitu" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "niedostÄpny" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "UÅŒyj polecenia pyload.py-s aby uzyskaÄ dostÄp do ustawieÅ" + diff --git a/locale/pl/LC_MESSAGES/pyLoad.mo b/locale/pl/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 31ea1e162..000000000 --- a/locale/pl/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/pl/LC_MESSAGES/pyLoad.po b/locale/pl/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..f7ca6734d --- /dev/null +++ b/locale/pl/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Polish\n" +"Language: pl_PL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Otrzymano sygnaÅ zakoÅczenia" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad jest juÅŒ uruchomiony - proces %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Niepowodzenie przy zmianie grupy: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Niepowodzenie przy zmianie uÅŒytkownika: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "katalog na logi" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Rozpoczynam" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "UÅŒywam katalogu domowego: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto deszyfruje pliki kontenera" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "katalog dla plików tymczasowych" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "katalog na pobrane pliki" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL dla poÅÄ
czenia szyfrowanego" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "PrzenoszÄ starÄ
konfiguracjÄ uÅŒytkownika do Bazy Danych" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Sprawdź dane logowania komendÄ
./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Wszystkie linki zostaÅy usuniÄte" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "Czas pobierania: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Wolne miejsce: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Aktywacja kont ..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "WÅÄ
czanie wtyczek ..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad jest uruchomiony i dziaÅa" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "restartujÄ pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad koÅczy dziaÅanie" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Zainstaluj %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "nie moÅŒna znaleÅºÄ %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "nie moÅŒna utworzyÄ %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "wyÅÄ
czanie..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "bÅÄ
d przy wyÅÄ
czaniu" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "proces pyLoad wyÅÄ
czono z poziomu terminala" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "Baza plików zostaÅa usuniÄta z powodu braku niekompatybilnej wersji." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Nie moÅŒna przekonwertowaÄ Bazy plików." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Przekonwertowano BazÄ Danych z wersji v2 do v3. " + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Przekonwertowano BazÄ Danych z wersji v3 do v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "KonwertujÄ bazÄ Django do nowszej wersji" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "zakoÅczono" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "zakolejkowane" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "pominiÄte" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "oczekujÄ" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "tymczasowo offline" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "rozpoczynam" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "niepowodzenie" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "anulowno" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "rozkodowujÄ" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "wÅasny" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "pobieranie" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "przetwarzanie" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "nieznany" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paczka ukoÅczona: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "UÅŒyj SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "BÅÄ
d zdalnego zaplecza: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Uruchamiam %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "BÅad Åadowania backendu %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "czekaj %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "Nie znaleziono certyfikatów SSL." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Nie zalecamy uruchamiania %s bezpoÅrednio z pyLoad - zaprzestano wsparcia" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "MoÅŒesz wykorzystaÄ wielowÄ
tkowy serwer oferujÄ
cy dobrÄ
wydajnoÅÄ i szyfrowanie ssl," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "oczywiÅcie nadal moÅŒesz uÅŒywaÄ %s z serwerem pyLoad fastcgi " + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "przykÅadowe konfiguracje znajdziesz w podkatalogu module/webui/servers " + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Nie moÅŒna uÅŒyÄ %(server)s - niezainstalowany python-flup " + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "BÅÄ
d importu lightweight server: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "NaleÅŒy pobraÄ i skompilowaÄ bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Skopiuj plik boern.so do folderu module/lib lub uÅŒyj polecenia setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "OczywiÅcie trzeba znaÄ Linuksa i wiedzieÄ, jak siÄ kompiluje programy" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Ze wzglÄdu na znane problemy z wydajnoÅciÄ
w systemie Windows ustaw serwer na threaded" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Ten serwer nie wspiera SSL, naleÅŒy rozwaÅŒyÄ uÅŒycie serwera threaded" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Uruchamiam wbudowany webserwer: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Uruchamiam wielowÄ
tkowy webserwer z szyfrowaniem SSL: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Uruchamiam wielowÄ
tkowy serwer: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Uruchamiam serwer fastcgi: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Uruchamianie serwera lightweight (bjoern):% (host) s:% (port) d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Nie posiadasz uprawnieÅ dostÄpu do tej strony." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Nie znaleziono katalogu pobierania." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "Bez limitu" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "niedostÄpny" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "UÅŒyj polecenia pyload.py-s aby uzyskaÄ dostÄp do ustawieÅ" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "Pobranie fragmentów nie powiodÅo siÄ, powrót do pojedynczego poÅÄ
czenia | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Pobieranie rozpocznie siÄ: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Pobieranie zakoÅczono: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Wtyczka %s nie zawiera funkcji." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Pobieranie przerwane: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Pobieram ponownie: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Pobieranie jest wyÅÄ
czone: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Pobieranie jest tymczasowo niedostÄpne:% s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Pobieranie nie powiodÅo siÄ: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Brak poÅÄ
czenia z hostem lub poÅÄ
czenie zostaÅo zresetowane, zaczekaj 1 minutÄ i spróbuj ponownie." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "PominiÄto pobieranie: %(name)s z powodu %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "RozpoczÄto rozszyfrowywanie: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "Rozszyfrowywanie nie powiodÅo siÄ: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Ponawianie %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Pobieranie informacji o %(name)s nie powiodÅo siÄ | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "BÅÄ
d przy uruchomieniu: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Nie powiodÅa siÄ aktywacja %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Aktywne wtyczki:% s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Nieaktywne wtyczki:% s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Nieudane ponowne ÅÄ
czenie: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Nie znaleziono skryptu ponownego ÅÄ
czenia!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Uruchamiam ponowne ÅÄ
czenie" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Niepowodzenie przy uruchamianiu skryptu ponownego ÅÄ
czenia!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Ponownie poÅÄ
czony, nowe IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Zbyt maÅo miejsca na dysku" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Nie moÅŒna zalogowaÄ siÄ na koncie %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "HasÅo nieprawidÅowe" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "Format czasu %s jest nieprawidÅowy, uÅŒyj: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "Konto % s generuje zbyt maÅy ruch, sprawdź ponownie za 30min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "Konto %s wygasÅo, sprawdź ponownie za 1godz" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "OsiÄ
gniÄto limit transferu" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s zawiera bÅÄdny wzorzec." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "BÅÄ
d przy imporcie %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Nie zaÅadowano Hostera" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Uaktywnij pobieranie bezpoÅrednie w ustawieniach swojego konta Bitshare" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "Nie moÅŒna wyczyÅciÄ zawartoÅci LinkList." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "Ustawienia konta usuniÄto po wprowadzeniu nowego formatu konfiguracji." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Wymagana autoryzacja (uÅŒytkownik:hasÅo)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "ProszÄ wejÅÄ na konto %s lub wyÅÄ
czyÄ wtyczkÄ" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "W pobranym pliku (%s) byÅ kod HTML... przekierowanie bÅÄdu? Pobieranie zostanie uruchomione ponownie." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Plik czasowo niedostÄpny" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: Oczekiwanie pomiÄdzy pobraniami %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: czekam na captcha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "Pobrany plik byÅ pusty" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "niepoprawny klucz API" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: PozostaÅo zbyt maÅo transferu" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Przekroczono transfer" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: WspóÅdzielenie ruchu (bezpoÅrednie pobieranie)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Trwa pobieranie spod tego adresu IP. Odczekaj 60 sekund" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "BÅÄdny kod autoryzacji. Pobieranie zostanie wznowione" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidshareCom: Brak wolnych slotów" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Ten plik wymaga konta premium" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "ZgÅoszono nieprawidÅowÄ
nazwÄ pliku" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "BÅÄ
d równolegÅego pobierania, odczekaj 60s." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Nie zalogowany." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Odszyfrowywanie nie powiodÅo siÄ" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "Nie umieszczono plik klucza w adresie URL" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Kod bÅÄdu:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Plik nie istnieje." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Wtyczki zostaÅy zaktualizowane, proszÄ zrestartowaÄ pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Wtyczki zaktualizowane i przeÅadowane" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Brak dostÄpnych aktualizacji wtyczek" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Brak aktualizacji dla pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** DostÄpna nowa wersja %s ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Pobierz stÄ
d: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Brak poÅÄ
czenia z serwerem aktualizacji" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nowa wersja %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Podczas aktualizacji wystÄ
piÅ blÄ
d %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "NiezgodnoÅÄ wersji" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Pobieranie zakoÅczono: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nowe ÅŒÄ
danie captcha: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "W odpowiedzi uÅŒyj 'c %s tekst z captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "Najpierw dodaj swoje konto premium.to i zrestartuj pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Dodano %s z HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "Nie zainstalowano %s" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Nie moÅŒna aktywowaÄ %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Aktywowany" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Brak aktywnych wtyczek do rozpakowywania plików" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Pakiet %s zakolejkowany do rozpakowania" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Sprawdzanie paczki %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Wypakowano %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Nie znaleziono plików do rozpakowania" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "wypakowujÄ" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Zabezpieczone haÅsem" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "NieprawidÅowe hasÅo" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Usuwanie %s plików" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Wypakowanie zakoÅczone" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "BÅÄ
d archiwum" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "NieprawidÅowa suma kontrolna CRC" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "WystÄ
piÅ nieznany bÅÄ
d" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Ustawienie uÅŒytkowników i grup nie powiodÅo siÄ: %s" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Wtyczka Click'N'Load: Port 9666 jest zajÄty" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "PozostaÅo %s punktów" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Nie moÅŒe wysÅaÄ odpowiedzi." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Posiadasz zbyt maÅÄ
iloÅÄ punktów na koncie CaptchaTrader" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Nie odnaleziono listy Crypter" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Lista Crypter jest pusta" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Pobieranie zakoÅczono: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Nowe CaptchaID z uploadu: %s: %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Twoje konto captcha 9kw.eu nie ma wystarczajÄ
co kredytów" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "Zainstalowane skrypty dla %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Niewykonywalny skrypt:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "BÅÄ
d w %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Twoje konto ExpertDecoders nie ma wystarczajÄ
co kredytów" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Najpierw dodaj swoje konto rehost.to i zrestartuj pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "Dodaj najpierw waÅŒne konto premiumize.me i zrestartuj pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "PozostaÅo %s punktów" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Nie zainstalowano moduÅów pil i tesseract oraz brak poÅÄ
czenia z serwisem dekodujÄ
cym captcha" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Å»aden z serwisów nie odkodowal captcha w dopuszczalnym czasie. " + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Ustawienia uÅŒytkowników i grup nie powiodÅo siÄ: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Odkodowanie Captcha nieaktywne" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Dodano paczkÄ %(name)s zawierajÄ
cÄ
%(count)d linków" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Dodano %(count)d linków do paczki #%(package)d" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Nie znaleziono silnika JavaScript, zainstaluj SpiderMonkey, ossp-js, pyv8 lub rhino" + diff --git a/locale/pl/LC_MESSAGES/pyLoadCli.mo b/locale/pl/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 565f26e3a..000000000 --- a/locale/pl/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/pl/LC_MESSAGES/pyLoadCli.po b/locale/pl/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..eebdeeba7 --- /dev/null +++ b/locale/pl/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Polish\n" +"Language: pl_PL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "Interfejs Linii Komend" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s PobraÅ:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "PrÄdkoÅÄ:" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "Rozmiar:" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "ZakoÅczono w:" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "ID:" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "Oczekiwanie:" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "Wstrzymane" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "Aktywne" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "PrÄdkoÅÄ pobierania" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Pliki w kolejce" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "OgóÅem" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "Dodaj linki" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " ZarzÄ
dzaj kolejkÄ
" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "Â ZarzÄ
dzanie poczekalniÄ
linków" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "Zatrzymaj/Wznów serwer" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "WyÅÄ
cz serwer" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "WyjÅcie" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "UÅŒywamy skÅadni: add <Package name> <link> <link2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Sprawdzanie linków %d:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Plik nie istnieje." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad zostaÅ wyÅÄ
czony" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "WyÅwietla status serwera" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "WyÅwietla pobierane pliki z kolejki" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "WyÅwietla pobierane pliki z poczekalni" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Dodaje pakiet do kolejki" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Dodaje paczkÄ do poczekalni" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "UsuÅ pliki z Kolejki/Poczekalni" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "UsuÅ Paczki z Kolejki/Poczekalni" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Przenoszenie paczek z kolejki do poczekalni i odwrotnie" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Zrestartuj pliki" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Zrestartuj paczki" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Sprawdź status online, wspóÅpracuje z lokalnym kontenerem" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Sprawdź stan online pliku kontenera" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Wstrzymaj serwer" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "kontynuuj pobieranie" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Wstrzymaj/Wznów" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "wyÅÄ
cz serwer" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Lista poleceÅ:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Nie moÅŒna zapisaÄ pliku konfiguracyjnego" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Do poÅÄ
czenia z pyLoad Core wymagana jest instalacja py-openssl." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adres:" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Port:" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "UÅŒytkownik:" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "HasÅo:" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "BÅÄdne dane logowania." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Nie moÅŒna poÅÄ
czyÄ z %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Do poÅÄ
czenia z pyLoad Core wymagana jest instalacja py-openssl." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Tryb interaktywny wyÅÄ
czono po wprowadzonych komendach." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Dodaj pakiet:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Wprowadź nazwÄ dla nowego pakietu" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Pakiet: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Analizuj linki które chcesz dodaÄ." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Napisz %s gdy ukoÅczone." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Dodanych linków:" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "powrót do gÅównego menu" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "ZarzÄ
dzanie pakietami:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "ZarzÄ
dzaj linkami:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Czy chcesz przenieÅÄ?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Czy na pewno chcesz usunÄ
Ä?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Czy chcesz zrestartowaÄ?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Wybierz, co chcesz wykonaÄ lub wprowadź numer paczki." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "skasuj" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "przenieÅ" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "Restart" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "- poprzedni" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - nastÄpny" + diff --git a/locale/pl/LC_MESSAGES/pyLoadGui.mo b/locale/pl/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index bbfcb176e..000000000 --- a/locale/pl/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/pl/LC_MESSAGES/setup.mo b/locale/pl/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index c8303602c..000000000 --- a/locale/pl/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/pl/LC_MESSAGES/setup.po b/locale/pl/LC_MESSAGES/setup.po new file mode 100644 index 000000000..9bebff39f --- /dev/null +++ b/locale/pl/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Polish\n" +"Language: pl_PL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "t" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Witamy w asystencie konfiguracji pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Dokona sprawdzenia systemu i ustawi podstawowe parametry potrzebne do uruchomienia pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "WartoÅÄ w nawiasach kwadratowych [] jest zawsze domyÅlnÄ
," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "jeÅli nie chcesz zmieniaÄ wartoÅci lub nie masz pewnoÅci co wybraÄ, naciÅnij enter." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Nie zapomnij: kiedy uruchamiasz pyload.py zawsze moÅŒesz ponownie wybraÄ asystenta dodajÄ
c parametr --setup lub -s." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "JeÅli masz jakiekolwiek problemy z asystentem wciÅnij Ctlr-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "aby go zatrzymaÄ i nie pozwoliÄ mu automatycznie uruchomiÄ siÄ z pyload.py . " + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "NaciÅnij enter jak bÄdziesz gotowy na sprawdzenie systemu." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Potrzebujesz pycurl, sqlite i pythona 2.5, 2.6 lub 2.7 aby uruchomiÄ pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "ProszÄ popraw to i ponownie uruchom pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "Instalator teraz zakoÅczy dziaÅanie." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "ZakoÅczono sprawdzanie systemu, naciÅnij enter w celu obejrzenia raportu." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Stan ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "rozszyfrowywanie kontenerów" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "poÅÄ
czenie SSL" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "automatyczne rozpoznawanie captcha" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Interfejs Web" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "rozszerzone Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "DostÄpne funkcje:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "NiedostÄpne funkcje:" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto jest niedostÄpny" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Potrzebujesz go jeÅli chcesz rozszyfrowywaÄ pliki kontenerowe." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL niedostÄpny" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Jest to potrzebne jeÅli chcesz nawiÄ
zywaÄ szyfrowane poÅÄ
czenia z Core lub interfejsem Web." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "JeÅli chcesz mieÄ dostÄp tylko lokalny - SSL nie jest uÅŒyteczne." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "brak rozpoznawania captcha" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Potrzebne tylko do niektórych serwisów dla kont darmowych." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "Interfejs graficzny niedostÄpny" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "Graficzny Interfejs UÅŒytkownika." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "nie znaleziono silnika JavaScript" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Do dodania kilku linków jednoczeÅnie bÄdziesz potrzebowaÅ Click'N'Load. Zainstaluj SpiderMonkey, ossp-js, pyv8 lub rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "MoÅŒesz przerwaÄ instalator i naprawiÄ niektóre zaleÅŒnoÅci." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "KontynuowaÄ instalacjÄ?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Czy chcesz zmieniÄ ÅcieÅŒkÄ do plików konfiguracji? Obecnie to %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "JeÅli uÅŒywasz pyLoad'a na serwerze lub partycji home która znajduje siÄ na pamiÄci flash - dobrym pomysÅem moÅŒe byÄ zmiana tego parametru." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "ZmieniÄ ÅcieÅŒkÄ dla plików konfiguracji?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Czy chcesz dokonaÄ konfiguracji logowania i ustawieÅ podstawowych?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Jest to wymagane przy pierwszym uruchomieniu." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "StworzyÄ podstawowe ustawienia?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Czy chcesz ustawiÄ SSL?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "UstawiÄ SSL?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Czy chcesz ustawiÄ interfejs Web?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "UstawiÄ interfejs Web?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Instalacja zakoÅczona pomyÅlnie." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "NaciÅnij enter aby wyjÅÄ i ponownie uruchom pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Sprawdzenie systemu ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Zainstalowana wersja Python'a jest zbyt nowa, ProszÄ uÅŒyÄ wersji 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Zainstalowana wersja Python'a jest zbyt stara, ProszÄ uÅŒyÄ przynajmniej wersji 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Wersja Python'a: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Zainstalowana jinja2 w wersji %s jest przestarzaÅa." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "MoÅŒesz kontynuowaÄ pracÄ, ale interfejs Web nie bÄdzie czynny," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "uaktualnij lub odinstaluj, pyLoad zawiera odpowiedniÄ
wersjÄ biblioteki jinja2." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "silnik Java Skrypt" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Podstawowe Ustawienia ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "NastÄpujÄ
ce parametry logowania sÄ
odpowiednie dla CLI, GUI i interfejsu Web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Nazwa uÅŒytkownika" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Klienty zewnÄtrzne (GUI, CLI lub inne) potrzebujÄ
zdalnego poÅÄ
czenia do dziaÅania przez sieÄ." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "JeÅŒeli chcesz uÅŒywaÄ tylko interfejsu web moÅŒesz dezaktywowaÄ to aby zaoszczÄdziÄ pamiÄÄ." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "WÅÄ
cz zdalny dostÄp" + +#: module/setup.py:291 +msgid "Language" +msgstr "JÄzyk" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Folder pobierania" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Maksymalna liczba jednoczesnych pobraÅ" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "UÅŒywaÄ ponownego ÅÄ
czenia?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Lokalizacja skryptu do ponownego ÅÄ
czenia" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Ustawienia interfejsu Web ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "AktywowaÄ interfejs Web?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Adres do nasÅuchu, jeÅli uÅŒyjesz 127.0.0.1 lub localhost, interfejs Web bÄdzie dostÄpny jedynie lokalnie." + +#: module/setup.py:312 +msgid "Address" +msgstr "Adres" + +#: module/setup.py:313 +msgid "Port" +msgstr "Port" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad oferuje kilka typów serwerów backends, a teraz po krótce wyjaÅniam." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Serwer domyÅlny, najlepszy wybór, jeÅli nie wiesz który wybraÄ." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Ten serwer wspiera SSL i jest dobrÄ
alternatywÄ
dla builtin." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "MoÅŒe byÄ uÅŒywany przez apache, lighttpd, wymaga od Ciebie ich konfiguracji, która nie jest zbyt Åatwym zadaniem." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Bardzo szybka alternatywa, napisany w C, wymaga libev i znajomoÅci Linuxa" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Pobierz go stÄ
d: https://github.com/jonashaag/bjoern, i skompiluj go" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "i skopiuj plik bjoern.so do katalogu module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Uwaga: W pewnych, rzadkich przypadkach serwer builtin nie dziaÅa, jeÅli wystÄpujÄ
problemy z interfejsem WWW" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "wrÃ³Ä tu i zmieÅ serwer builtin na threaded" + +#: module/setup.py:329 +msgid "Server" +msgstr "Serwer" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## Ustawienia SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "W celu wygenerowania certyfikatów ssl uruchom nastÄpujÄ
ce komendy z katalogu pyload:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "JeÅli wszystko pomyÅlnie siÄ zakoÅczyÅo, moÅŒesz aktywowaÄ SSL." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "AktywowaÄ SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Wybierz dziaÅanie" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1- Utwórz/Edutuj uÅŒytkownika" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2- PokaÅŒ uÅŒytkowników" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - UsuÅ uÅŒytkownika" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4- WyjÅcie" + +#: module/setup.py:376 +msgid "Users" +msgstr "UÅŒytkownicy" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Ustawiam nowÄ
ÅcieÅŒkÄ do plików konfiguracji, obecna konfiguracja nie zostanie tam przeniesiona!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "ÅcieÅŒka do plików konfiguracji" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "ÅcieÅŒka do plików konfiguracji zostaÅa zmieniona, Instalator zostanie teraz zamkniÄty, uruchom go ponownie, aby przejÅÄ dalej." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "NaciÅnij Enter aby zakoÅczyÄ." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Ustawienie ÅcieÅŒki do plików konfiguracji nie powiodÅo siÄ: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: brakuje" + +#: module/setup.py:464 +msgid "Password: " +msgstr "HasÅo:" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "HasÅo za krótkie. UÅŒyj przynajmniej 4 znaków." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "HasÅo (ponownie):" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "HasÅo nie pasuje" + +#: module/setup.py:493 +msgid "yes" +msgstr "tak" + +#: module/setup.py:493 +msgid "true" +msgstr "prawda" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "nie" + +#: module/setup.py:496 +msgid "false" +msgstr "faÅsz" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "BÅÄdne dane" + diff --git a/locale/pt/LC_MESSAGES/django.po b/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 000000000..6b0a4f5bc --- /dev/null +++ b/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Portuguese, Brazilian\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Pedir novo Captcha" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Por favor leia o texto do captcha." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad reiniciou" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "desligado" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "Sucesso" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "ligado" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Tem a certeza que quer sair do pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Reiniciar Link" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Apagar Link" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Introduza o nome do pacote." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Por favor clique na posição correta do captcha." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Ocorreu um erro." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Pasta vazia" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "Falhou" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Sem Captchas para ler." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "As senhas não correspondem." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Configurações guardadas." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Nova pasta" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Tem a certeza que deseja reiniciar o pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Downloads Activos" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Inicio" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Registo de ocorrências" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Configuração" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Nome" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Status" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Informação" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Tamanho" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Progresso" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Login" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Nome do usuário" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Senha" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "O utilizador e a senha não correspondem. Tente novamente." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Para restabelecer a sua informação de login ou adicionar um utilizador execute:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Apagar os terminados" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "ReinÃcio falhou" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Pasta:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Senha:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Editar Pacote" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Edite os detalhes do pacote abaixo." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "O nome do pacote." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Pasta" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Nome da sub-pasta para estes downloads." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Lista das passwords usadas para extrair." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Enviar" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Restabelecer" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Terminou a sessão com sucesso." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Caminho" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absoluto" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativo" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "nome" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "tamanho" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "tipo" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "última modificação" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "diretoria superior" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "sem conteúdo" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Geral" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Contas" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "Escolha uma das secções do menu" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Válida até" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Tráfego remanescente" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Tempo" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Máximos Paralelos" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Apagar?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "válido" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "não válido" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "sim" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "não" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Adicionar" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Adicionar conta" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Introduza os dados da sua conta para utilizar as caracterÃsticas premium." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "O seu nome de utilizador." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "A senha para esta conta." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "Tipo" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Escolha o host da sua conta." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Iniciar" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "anterior" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "próximo" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Fim" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Novidades" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Ajuda" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Sistema" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "SO:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "Versão do pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Pasta de instalação:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Pasta das configurações:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Pasta de Downloads:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Espaço Livre:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Idioma:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Porta do Webinterface:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Porta do interface remoto:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Configurações" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Adicionar pacote" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Introduza os seus links ou carregue um container." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Nome do novo pacote." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Introduza aqui os seus links ou texto e carregue no botão filtrar." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtrar urls" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Senha para o arquivo RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Ficheiro" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Carregar um container." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Destino" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "A ler captcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "O captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Texto" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Introduza o texto do captcha." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Fechar" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "Atualização do pyLoad disponÃvel!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins atualizados, por favor reinicie!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha a aguardar" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Sair" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrar" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Informações" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Inicie a Sessão!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Parar" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Cancelar" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Restabelecer ligação:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Velocidade:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Activo:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Atualizar página" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "a carregar" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Voltar para o topo" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Sair do pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Reiniciar pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Para adicionar um utilizador ou alterar senhas utilize:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Importante: o Administrador tem sempre todas as permissões!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Alterar a senha" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "Administrador" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Permissões" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "alterar" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Introduza a sua senha actual e a desejada." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Utilizador" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Senha atual" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nova senha" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "A nova senha." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "A nova senha (repetir)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Por favor repita a nova senha." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ilimitado" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/pt/LC_MESSAGES/pyLoad.po b/locale/pt/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..00f04a239 --- /dev/null +++ b/locale/pt/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Portuguese, Brazilian\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "sinal de Sair recebido" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad já está rodando com pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Falha ao trocar grupo: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Falha ao trocar de usuario: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Iniciando" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Usando diretório: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Todos os links foram removidos" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Espaço livre: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Ativando contas..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad está rodando" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "reiniciando pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad fechou" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "desligando..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "erro durante desligamento" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "Terminado" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "Offline" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "Online" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "em fila" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "ignorada" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "esperando" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "Temp. off-line" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "iniciando" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "falhou" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "abortada" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "descriptografando" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "personalizado" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "Transferindo" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "processando" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "desconhecido" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Pacote finalizado: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Erro de back-end remoto: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Iniciando %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Falha ao carregar back-end %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "Certificado SSL não encontrado." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Este servidor não oferece SSL, por favor, considere usar HTTP{?} em vez disso" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ilimitado" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "pedaços do Download falharam, retornar para conexão simples |%s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "Inicio do Download: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "Termino do Download: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Plugin %s está sem uma função." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "Download abortado: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "Download reiniciado: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "Download está offline: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "Download esta temporariamente offline: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "Download falhou: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "ImpossÃvel conectar com o host ou a conexão receptou, tentar novamente em 1 minuto." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "Download pulado: %(name)s pois %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Busca de informações para %(name)s falhou|%(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Falha de ativação %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Reconectar Falhou: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Script de reconexão não encontrado!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Iniciando reconexão" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Falha ao executar script de reconexão!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Reconectado, novo IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Espaço insuficiente no dispositivo" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Não pode ligar com a conta %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Senha incorreta" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "A conta %s não tem tráfego suficiente, checando novamente em 30 min" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "A conta %s expirou, checando novamente em 1h" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "Limite de Download alcançado" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Erro ao importar %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Nenhum Hoster carregado" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Ativar Download direto em sua conta Bitshare" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Autorização necessaria (nome de usuario: senha)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "Por favor entre sua %s conta ou desative este plugin" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "Havia código HTML no arquivo baixado (%s)...erro de redirecionamento? O Download vai ser reiniciado." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Arquivo temporariamente indisponÃvel" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: esperar entre os Downloads %d s." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: esperando por capacha %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "Arquivo baixado estava vazio" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "Chave de API inválida" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: Tráfego restante insuficiente" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Tráfego excedido" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Compartilhamento de tráfego (Download direto)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Ja está baixando deste endereço de ip, espere 60 segundos" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Código de autenticação invalido, Download vai ser reiniciado" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: Sem slots vazios" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Você precisa de uma conta premium para este arquivo" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Nome do arquivo relatado como invalido" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Erro de Download paralelo, esperar 60 segundos." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "Não está logado." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "Descriptografia falhou" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "Nenhum arquivo chave fornecido na URL" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Codigo do erro:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Plugins foram atualizados, por favor reinicie o pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Plugins atualizados e recarregados" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Nenhuma atualização de plugin disponÃvel" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "Nenhuma atualização para o pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "* * * Nova versão %s do pyLoad disponÃvel * * *" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "* * * faça o Download em : http://pyload.org/download * * *" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "ImpossÃvel conectar com o servidor de atualizações" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Nova versão de %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "Erro ao atualizar %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "Incompatibilidade de versão" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "Download concluÃdo: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Nova solicitação de Captcha: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "Responder com 'c %s o texto no captcha'" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "Adicionado %s de HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "Sem %s instalado" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Não foi possÃvel activar o %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Ativado" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Não ha plugins de extração ativos" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "Pacote %s enfileirados para extração posterior" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "Verificar pacote %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "Extrair para %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Arquivos não encontrados para extrair" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "extraindo" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Protegido por senha" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Senha incorreta" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "Excluindo %s arquivos" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Extração terminada" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "Erro de arquivo" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "Incompatibilidade de CRC" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Erro desconhecido" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Configuração de usuário e grupo falhou" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'n'Load: porta 9666 já está em uso" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s créditos sobrando" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Não pode enviar resposta." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Sua conta CaptchaTrader não tem créditos suficientes" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Lista do Crypter não encontrada" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Lista do Crypter vazia" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "Download terminado: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Novo CaptchaID do upload: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Sua conta 9kw.eu não tem créditos suficientes" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "scripts instalados para %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Scrip não executável:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Erro em %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "Sua conta ExpertDecoders não tem créditos suficientes" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "Por favo adicione sua conta rehost.to antes de reiniciar o pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d créditos sobrando" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil e tesseract não estão instalados e nenhum cliente está conectado para reconhecimento de captcha" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Configuração de usuário e grupo falhou: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/pt/LC_MESSAGES/pyLoadCli.po b/locale/pt/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..49a9ff501 --- /dev/null +++ b/locale/pt/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Portuguese, Brazilian\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Interface de Linha de Comandos" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Velocidade: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Tamanho: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " Terminado em: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "em espera: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Estado:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "pausados" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "em execução" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "Velocidade total" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Arquivos na fila" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Adicionar Links" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Gerir Fila" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " Gerir Coletor" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " Parar/Retomar servidor" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Terminar Servidor" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Sair" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "Por favor, use esta sintaxe: Adicionar <Nome do Pacote> <link> <link2>..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Checar %d links:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "O arquivo não existe." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad foi finalizado" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Estado do servidor de impressões" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Cópias de downloads na fila" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Cópias de downloads no coletor" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "Adicionar pacotes para a fila" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Adicionar pacotes para o coletor" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Deletar arquivos da fila/coletor" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Deletar pacotes da fila/coletor" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Mover pacotes da fila para o coletor ou vice-versa" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Reiniciar arquivos" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Reiniciar pacotes" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Verificar o estado online, trabalhar com recipiente local" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Verifica o estado online de um arquivo de contêiner" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Colocar servidor em Pausa" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "continuar downloads" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Alternar pausa/retomar" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "terminar servidor" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Lista de comandos:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Não foi possÃvel escrever o arquivo de configuração do usuário" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Endereço: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Porta: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Nome do usuário: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Senha: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Dados de login estão errados." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Não conseguiu estabelecer conexão com %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "você precisa do py-openssl para se conectar com o pyLoad core." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "O modo interativo foi ignorado pois alguns comandos foram pulados por você." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Adicionar Pacote:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Insira um nome para o novo pacote" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Pacote: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Analise os links que você deseja adicionar." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Digite %s quando terminar." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Links adicionados: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " voltar ao menu principal" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Gerenciar pacotes:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Gerenciar Links:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "O que você deseja mover?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "O que você deseja excluir?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "O que você deseja reiniciar?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "deletar" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "mover" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "reiniciar" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - anterior" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - próximo" + diff --git a/locale/pt/LC_MESSAGES/setup.po b/locale/pt/LC_MESSAGES/setup.po new file mode 100644 index 000000000..66923aa8d --- /dev/null +++ b/locale/pt/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Portuguese, Brazilian\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "s" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "Bem-vindo ao assistente de configuração do pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Ele irá verificar o seu sistema e fazer uma configuração básica para executar o pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "O valor entre colchetes [] é sempre o valor padrão," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "no caso de você não quer mudá-lo ou você não tiver certeza qual escolher, apenas tecle enter." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Não se esqueça: você sempre pode executar novamente o assistente com os parâmetros --setup ou -s, quando você iniciar o pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "para cancelar e não deixá-lo iniciar automaticamente com pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Quando estiver pronto para verificação do sistema, aperte enter." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Continuar com a configuração?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Você quer alterar o caminho de configuração? O atual é %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Alterar o caminho de configuração?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Você quer configurar dados de login e configurações básicas?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Isto é recomendável para a primeira execução." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Fazer a configuração básica?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Você quer configurar o ssl?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Configurar o ssl?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Você quer configurar a interface WEB?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Configurar a interface Web?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Configuração concluÃda com êxito." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Aperte enter para sair e reiniciar o pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "# # Instalação basica # #" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Os dados de login à seguir é válido para o CLI, GUI e interface Web." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Nome do usuário" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "LÃngua" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "nº Downloads paralelos" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "Usar Reconectar?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Local do script de reconexão" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "# # Instalação da interface WEB# #" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Ativar webinterface?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Endereço de escuta, se você usar 127.0.0.1 ou localhost, a interface Web será acessÃvel apenas localmente." + +#: module/setup.py:312 +msgid "Address" +msgstr "Endereço" + +#: module/setup.py:313 +msgid "Port" +msgstr "Porta" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "O pyLoad oferece vários backends de servidor, a seguir uma breve explicação." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Pode ser usado pelo apache, lighttpd, requer que você os configure, o que não é tarefa muito fácil." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Pegue-a daqui: https://github.com/jonashaag/bjoern, é só compilar" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Atenção: Em alguns casos raros o servidor builtin não está funcionando, se você notar problemas com a interface Web" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "Volte aqui e mude o servidor builtin para o threaded ." + +#: module/setup.py:329 +msgid "Server" +msgstr "Servidor" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "# # Configuração SSL # #" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Execute esses comandos na pasta de configuração do pyLoad para fazer certificados ssl:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Se você está pronto e tudo correu bem, você pode ativar o ssl agora." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "Ativar SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Selecione a ação" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Criar/editar usuário" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Lista de usuários" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Remover usuário" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Sair" + +#: module/setup.py:376 +msgid "Users" +msgstr "Usuários" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Pressione Enter para sair." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "A troca do caminho de configuração falhou: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Senha: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Senha muito curta. Use pelo menos 4 caracteres." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Senha (novamente): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "As senhas não correspondem." + +#: module/setup.py:493 +msgid "yes" +msgstr "sim" + +#: module/setup.py:493 +msgid "true" +msgstr "verdadeiro" + +#: module/setup.py:493 +msgid "t" +msgstr "v" + +#: module/setup.py:496 +msgid "no" +msgstr "não" + +#: module/setup.py:496 +msgid "false" +msgstr "falso" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Entrada inválida" + diff --git a/locale/pt_BR/LC_MESSAGES/django.mo b/locale/pt_BR/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index 2fdf540b0..000000000 --- a/locale/pt_BR/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/pt_BR/LC_MESSAGES/pyLoad.mo b/locale/pt_BR/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 2e8a1e5b3..000000000 --- a/locale/pt_BR/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/pt_BR/LC_MESSAGES/pyLoadCli.mo b/locale/pt_BR/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 2ca834196..000000000 --- a/locale/pt_BR/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/pt_BR/LC_MESSAGES/pyLoadGui.mo b/locale/pt_BR/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 28fe26252..000000000 --- a/locale/pt_BR/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/pt_BR/LC_MESSAGES/setup.mo b/locale/pt_BR/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index c64d0f23c..000000000 --- a/locale/pt_BR/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/ro/LC_MESSAGES/django.po b/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 000000000..6a4afa0d0 --- /dev/null +++ b/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Romanian\n" +"Language: ro_RO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100>0 && n%100<20)) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/ro/LC_MESSAGES/pyLoad.mo b/locale/ro/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 2c20cfbd4..000000000 --- a/locale/ro/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/ro/LC_MESSAGES/pyLoad.po b/locale/ro/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..e798cc988 --- /dev/null +++ b/locale/ro/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Romanian\n" +"Language: ro_RO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100>0 && n%100<20)) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/ro/LC_MESSAGES/pyLoadCli.mo b/locale/ro/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 1ae24953f..000000000 --- a/locale/ro/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/ro/LC_MESSAGES/pyLoadCli.po b/locale/ro/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..26a3f1f88 --- /dev/null +++ b/locale/ro/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Romanian\n" +"Language: ro_RO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100>0 && n%100<20)) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/ro/LC_MESSAGES/pyLoadGui.mo b/locale/ro/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 1ae24953f..000000000 --- a/locale/ro/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/ro/LC_MESSAGES/setup.po b/locale/ro/LC_MESSAGES/setup.po new file mode 100644 index 000000000..aed4d803e --- /dev/null +++ b/locale/ro/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Romanian\n" +"Language: ro_RO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100>0 && n%100<20)) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/ru/LC_MESSAGES/django.mo b/locale/ru/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index 0a1394f21..000000000 --- a/locale/ru/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/ru/LC_MESSAGES/django.po b/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 000000000..908d4684d --- /dev/null +++ b/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Russian\n" +"Language: ru_RU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "ÐапÑÐŸÑ ÐœÐŸÐ²ÐŸÐ¹ каÑÑОМкО." + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "ÐÑПÑОÑайÑе ÑекÑÑ ÐœÐ° ÑОÑÑМке." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "ÐÑПгÑаЌЌа pyLoad заМПвП загÑÑжеМа." + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "вÑкл." + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "УÑпеÑМП" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "вкл." + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "ÐÑ ÑвеÑеМÑ, ÑÑП Ñ
ПÑОÑе закПМÑОÑÑ pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "ÐеÑезапÑÑÑОÑÑ ÑÑÑлкÑ" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "УЎалОÑÑ ÑÑÑлкÑ." + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "ÐвеЎОÑе ÐžÐŒÑ ÐºÐŸÐœÑейМеÑа." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "ÐПжалÑйÑÑа клОкМОÑе Ма пÑавОлÑМÑÑ Ð¿ÐŸÐ·ÐžÑÐžÑ ÐºÐ°ÑÑОМкО." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "СвеÑÑОлаÑÑ ÐŸÑОбка." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Ðапка пÑÑÑа" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "СбПй" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "ÐÐµÑ ÑОÑÑМка ÐŽÐ»Ñ Ð¿ÑПÑÑеМОÑ." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "ÐаÑПлО Ме ÑПвпаЎаÑÑ." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "CПÑ
ÑÐ°ÐœÐµÐœÐžÑ ÑÑÑаМПвПк завеÑÑОлаÑÑ." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "ÐÑ ÑвеÑеМÑ, ÑÑП Ñ
ПÑОÑе пеÑезагÑÑзОÑÑ pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "ПжОЎаМОе %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "ÐкÑОвМÑе загÑÑзкО" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "ÐПЌПй" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "ÐакаÑкО" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "ÐÑÑÑÑÑ" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "ÐаÑÑÑПйкО" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "ÐазваМОе" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "СÑаÑÑÑ" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "ÐМÑПÑЌаÑОÑ" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "РазЌеÑ" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "ÐÑПгÑеÑÑ" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "ÐПгОМ" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "ÐПлÑзПваÑелÑ" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "ÐаÑПлÑ" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "ÐепÑавОлÑМÑе ÐžÐŒÑ Ð¿ÐŸÐ»ÑзПваÑÐµÐ»Ñ ÐžÐ»Ðž паÑПлÑ! ÐПпÑПбÑйÑе еÑе Ñаз." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "ÐÐ»Ñ ÑбÑПÑа ÑвПОÑ
ЎаММÑÑ
ОлО ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÐœÐŸÐ²ÐŸÐ³ÐŸ пПлÑзПваÑÐµÐ»Ñ Ð·Ð°Ð¿ÑÑÑОÑе: " + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "УЎалОÑÑ Ð·Ð°Ð²ÐµÑÑÑММÑе" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "ÐеÑезапÑÑÑОÑÑ ÐœÐµÑЎавÑОеÑÑ" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Ðапка:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "ÐаÑПлÑ:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "РеЎакÑОÑПваÑÑ ÐºÐŸÐœÑейМеÑ" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "РеЎакÑОÑПваМОе ЎеÑалей кПМÑейМеÑа." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "ÐÐŒÑ ÐºÐŸÐœÑейМеÑа." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Ðапка" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "ÐÐŒÑ Ð¿ÐŸÐŽÐ¿Ð°Ð¿ÐºÐž ÐŽÐ»Ñ ÑÑОÑ
загÑÑзПк." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "СпОÑПк паÑПлей, ОÑпПлÑзÑеЌÑÑ
ÐŽÐ»Ñ ÑаÑпакПвкО." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "ÐÑпÑавОÑÑ" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "СбÑПÑ" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "ÐÑ ÑÑпеÑМП вÑÑлО." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "ÐÑÑÑ" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "абÑПлÑÑМÑй" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "ПÑМПÑОÑелÑМÑй" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "ОЌÑ" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "ÑазЌеÑ" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "ÑОп" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "пПÑлеЎМее ОзЌеМеМОе" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "ÑПЎОÑелÑÑÐºÐ°Ñ Ð¿Ð°Ð¿ÐºÐ°" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "ПÑÑÑÑÑÑвÑÐµÑ ÑПЎеÑжОЌПе" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "ÐÑМПвМÑе" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "ÐлагОМÑ" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "ÐккаÑМÑÑ" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "ÐÑбеÑОÑе ÑекÑÐžÑ ÐŒÐµÐœÑ" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "ÐÑОлПжеМОе" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "ÐÑеЌОÑÐŒ аккаÑМÑ" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "ÐПЎеМ ЎП" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "ÐÑÑалПÑÑ ÑÑаÑОка" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "ÐÑеЌÑ" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "ÐакÑ. пПÑПкПв" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "УЎалОÑÑ?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "ЎейÑÑвОÑелеМ" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "Ме гПЎеМ" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "Ўа" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "МеÑ" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "ÐПбавОÑÑ" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "ÐПбавлеМОе ÑÑеÑМПй запОÑО" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "УкажОÑе пÑеЌОÑÐŒ аккаÑÐœÑ ÐŽÐ»Ñ ÐžÑпПлÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ð²ÑеÑ
егП вПзЌПжМПÑÑей." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "ÐÐŒÑ Ð¿ÐŸÐ»ÑзПваÑелÑ." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "ÐаÑÐŸÐ»Ñ ÐŽÐ»Ñ ÑÑПй ÑÑеÑМПй запОÑО." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "ТОп" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "ÐÑбеÑОÑе Ñ
ПÑÑОМг." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "ÐаÑалП" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "пÑеЎ." + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "ÑлеЎ." + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "ÐПМеÑ" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "ÐПвПÑÑО" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "ÐПЎЎеÑжка" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "СОÑÑеЌа" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "ÐС:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "ÐеÑÑÐžÑ pyLoad:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Ðапка ÑÑÑаМПвкО:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Ðапка МаÑÑÑПек:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "Ðапка ÑкаÑаММПгП:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "СвПбПЎМП:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "ЯзÑк:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "ÐПÑÑ WEB ОМÑеÑÑейÑа:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "ÐПÑÑ ÑЎалеММПгП ÑпÑавлеМОÑ:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "УÑÑаМПвка" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Ѐайл ЌеМеЎжеÑ" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "ÐПбавОÑÑ ÐºÐŸÐœÑейМеÑ" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "ÐÑÑавÑÑе ÑÑÑлкО ОлО загÑÑзОÑе кПМÑейМеÑ." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "ÐÐŒÑ ÐœÐŸÐ²ÐŸÐ³ÐŸ кПМÑейМеÑа." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "СÑÑлкО" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "ÐÑÑавÑÑе зЎеÑÑ ÑÑÑлкО О МажЌОÑе \"ЀОлÑÑÑ\"" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "ЀОлÑÑÑ" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "ÐаÑÐŸÐ»Ñ ÐŽÐ»Ñ Ð°ÑÑ
Ова RAR" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Ѐайл" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "ÐагÑÑзОÑÑ ÐºÐŸÐœÑейМеÑ." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "ÐазМаÑеМОе" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "ЧÑеМОе каÑÑОМкО" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "ÐаÑÑОМка" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "ÐаÑÑОМка." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "ТекÑÑ" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "ÐвеЎОÑе ÑекÑÑ Ñ ÐºÐ°ÑÑОМкО." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "ÐакÑÑÑÑ" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Web-ОМÑеÑÑейÑ" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "ÐПÑÑÑÐ¿ÐœÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÑ pyLoad!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "ÐÐ»Ð°Ð³ÐžÐœÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÑ, пеÑезапÑÑÑОÑе pyLoad!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "ÐжОЎаеЌ ÑОÑÑМПк" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "ÐÑйÑО" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "ÐЎЌОМОÑÑÑОÑПваМОе" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "ÐМÑПÑЌаÑОÑ" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "ÐПжалÑйÑÑа, вПйЎОÑе ÑП ÑвПОЌО ÑÑÑÑМÑЌО ЎаММÑЌО!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "СÑПп" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "ÐÑЌеМОÑÑ" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "ÐагÑÑзка:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "ÐеÑепПЎклÑÑеМОе:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "СкПÑПÑÑÑ:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "ÐкÑОвМÑе:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "ÐбМПвОÑÑ ÑÑÑаМОÑÑ" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "загÑÑзка" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "ÐвеÑÑ
" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "ÐавеÑÑОÑÑ pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "ÐеÑезапÑÑÑОÑÑ pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "ÐÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ Ð¿ÐŸÐ»ÑзПваÑÐµÐ»Ñ ÐžÐ»Ðž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð¿Ð°ÑПлÑ:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "ÐМОЌаМОе: аЎЌОМОÑÑÑаÑÐŸÑ Ñже ÐŸÐ±Ð»Ð°ÐŽÐ°ÐµÑ Ð²ÑеЌО пÑаваЌО!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "ÐзЌеМОÑÑ Ð¿Ð°ÑПлÑ" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "ÐЎЌОМ" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "ÐÑава" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "ОзЌеМОÑÑ" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "ÐвеЎОÑе ÑекÑÑОй О желаеЌÑй паÑПлÑ." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "ÐПлÑзПваÑелÑ" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "ТекÑÑОй паÑПлÑ" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "ÐПвÑй паÑПлÑ" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "ÐПвÑй паÑПлÑ." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "ÐПвÑй паÑÐŸÐ»Ñ (пПвÑПÑ)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "ÐПжалÑйÑÑа пПвÑПÑОÑе МПвÑй паÑПлÑ." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "У Ð²Ð°Ñ ÐœÐµÑ Ð¿Ñав Ма пÑПÑЌПÑÑ ÑÑÑаМОÑÑ." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Ðапка ÐŽÐ»Ñ Ð·Ð°ÐºÐ°Ñек Ме МайЎеМа." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "МеПгÑаМОÑеММÑй" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "Ме ЎПÑÑÑпМП" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÐÐ»Ñ ÐŽÐŸÑÑÑпа к МаÑÑÑПйкаЌ запÑÑÑОÑе pyload.py -s." + diff --git a/locale/ru/LC_MESSAGES/pyLoad.mo b/locale/ru/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 156a1bc44..000000000 --- a/locale/ru/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/ru/LC_MESSAGES/pyLoad.po b/locale/ru/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..92dd4b2dc --- /dev/null +++ b/locale/ru/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Russian\n" +"Language: ru_RU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "ÐПлÑÑеМ ÑОгМал ÐŽÐ»Ñ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ ÑабПÑÑ" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad Ñже запÑÑеМ, pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Ðе ÑЎалПÑÑ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð³ÑÑппÑ: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Ðе ÑЎалПÑÑ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿ÐŸÐ»ÑзПваÑелÑ: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "папка ПÑÑеÑПв" + +#: module/Core.py:340 +msgid "Starting" +msgstr "ÐапÑÑкаеÑÑÑ" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "ÐÑÐœÐŸÐ²ÐœÐ°Ñ Ð¿Ð°Ð¿ÐºÐ°: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto ÐŽÐ»Ñ ÐŽÐµÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑайлПв кПМÑейМеÑПв" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "папка вÑеЌеММÑÑ
ÑайлПв" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "папка ÐŽÐ»Ñ Ð·Ð°ÐºÐ°Ñек" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL ÐŽÐ»Ñ Ð±ÐµÐ·ÐŸÐ¿Ð°ÑМПгП ÑПеЎОМеМОÑ" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "ÐеÑеЌеÑÑОÑÑ Ð¿ÑежМÑÑ Ð¿ÐŸÐ»ÑзПваÑелÑÑкÑÑ ÐºÐŸÐœÑОгÑÑаÑÐžÑ Ð² ÐÐ" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "ÐПжалÑйÑÑа, пÑПвеÑÑÑе ÑвПО ÑÑÑÑМÑе ЎаММÑе запÑÑÑОв ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "ÐÑе ÑÑÑлкО ÑЎалеМÑ" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "ÐÑÐµÐŒÑ Ð·Ð°ÐºÐ°ÑкО: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "СвПбПЎМПе ЌеÑÑП: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "ÐкÑОваÑÐžÑ Ð°ÐºÐºÐ°ÑМÑа..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "ÐкÑОваÑÐžÑ Ð¿Ð»Ð°Ð³ÐžÐœÐ°..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad загÑÑжеМ О ÑабПÑаеÑ" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "пеÑезапÑÑк pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "завеÑÑеМОе ÑабПÑÑ pyLoad" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "УÑÑаМПвка %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "Ме ÐŒÐŸÐ³Ñ ÐœÐ°Ð¹ÑО %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "Ме ÐŒÐŸÐ³Ñ ÑПзЎаÑÑ %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "завеÑÑеМОе ÑабПÑÑ..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "ПÑОбка пÑО завеÑÑеМОО ÑабПÑÑ" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "pyLoad ПÑÑаМПвлеМ Ñ ÑеÑЌОМала" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "ÐÐ°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
бÑла ÑЎалеМа пП пÑОÑОМе МеÑПвЌеÑÑОЌПй веÑÑОО." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Ðаза ЎаММÑÑ
ÐÐ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑеПбÑазПваМа." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Ðаза ЎаММÑÑ
пÑеПбÑазПваМа Оз v2 в v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Ðаза ЎаММÑÑ
пÑеПбÑазПваМа Оз v2 в v3." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "ÐÑеПбÑазПваМОе пÑежМей ÐÐ Django" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "закПМÑеМП" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "ПÑ-лайМ" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "ПМ-лайМ" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "в ПÑеÑеЎО" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "пÑПпÑÑеМП" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "ПжОЎаМОе" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "вÑеЌеММП МеЎПÑÑÑпМП" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "запÑÑкаеÑÑÑ" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "завеÑÑеМП Ñ ÐŸÑОбкПй" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "пÑеÑваМП" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "ÑаÑкПЎОÑПваМОе" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "пПлÑзПваÑелÑÑкОй" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "загÑÑжаеÑÑÑ" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "ПбÑабаÑÑваеÑÑÑ" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "МеОзвеÑÑМП" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "ÐÐ°ÐºÐµÑ Ð·Ð°Ð²ÐµÑÑеМ: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "ÐÑпПлÑзÑеÑÑÑ SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "ÐÑОбка ÑЎалеММПгП ÑеÑвОÑа: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "ÐапÑÑк %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "ÐÑОбка пÑО загÑÑзке %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "ПжОЎаМОе %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL ÑеÑÑОÑОкаÑÑ ÐœÐµ МайЎеМÑ." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Ð ÑПжалеМОÑ, пПЎЎеÑжка в pyLoad пÑекÑаÑеМа МаÑÐžÐœÐ°Ñ Ñ Ð²ÐµÑÑОО %s" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "ÐÑ ÐŒÐŸÐ¶ÐµÑе ОÑпПлÑзПваÑÑ threaded ÑеÑÐ²ÐµÑ ÐŽÐ»Ñ Ð¿ÐŸÐ²ÑÑÐµÐœÐžÑ Ð¿ÑПОзвПЎОÑелÑМПÑÑО О ОÑпПлÑÐ·ÐŸÐ²Ð°ÐœÐžÑ SSL," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "МП ЌПжМП О ОÑпПлÑзПваÑÑ Ð¿ÑежМОй ÑеÑÐ²ÐµÑ %s Ñ pyLoads fastcgi" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "ÐÑОЌеÑÑ ÐºÐŸÐœÑОгÑÑаÑОО web-ÑеÑвеÑПв ЌПжМП пПÑЌПÑÑеÑÑ Ð² папке module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "ÐÑпПлÑзПваÑÑ %(server)s МевПзЌПжМП, Ñак как Ме ÑÑÑаМПвлеМ python-flup!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "ÐÑÐŸÑ ÑеÑÐ²ÐµÑ ÐœÐµ пÑеЎПÑÑавлÑÐµÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÐžÑпПлÑзПваÑÑ SSL, пПжалÑйÑÑа ÑаÑÑЌПÑÑОÑе вПзЌПжМПÑÑÑ ÐžÑпПлÑзПваÑÑ ÑеÑÐ²ÐµÑ threaded взаЌеМ вÑбÑаММПгП" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "ÐапÑÑк вÑÑÑПеММПгП веб-ÑеÑвеÑа django: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "ÐапÑÑк веб-ÑеÑвеÑа lighttpd: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "ÐапÑÑк threaded веб-ÑеÑвеÑа: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "ÐапÑÑк fastcgi-ÑеÑвеÑа: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "У Ð²Ð°Ñ ÐœÐµÑ Ð¿Ñав Ма пÑПÑЌПÑÑ ÑÑÑаМОÑÑ." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "Ðапка ÐŽÐ»Ñ Ð·Ð°ÐºÐ°Ñек Ме МайЎеМа." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "МеПгÑаМОÑеММÑй" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "Ме ЎПÑÑÑпМП" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÐÐ»Ñ ÐŽÐŸÑÑÑпа к МаÑÑÑПйкаЌ запÑÑÑОÑе pyload.py -s." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "ÐагÑÑзка паÑаллелÑМÑÑ
пПÑПкПв ЎаММÑÑ
завеÑÑеМа Ñ ÐŸÑОбкаЌО, вПзвÑÐ°Ñ Ðº ПЎМПпПÑПÑМПй загÑÑзке | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "ÐагÑÑзка МаÑаÑа: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "ÐагÑÑзка завеÑÑеМа: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "РплагОМе %s ÐœÐµÑ ÑÑМкÑОО." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "ÐагÑÑзка пÑеÑваМа: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "ÐÑОбка загÑÑзкО: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "ÐагÑÑзка МеЎПÑÑÑпМа: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "ÐагÑÑзка вÑеЌеММП МеЎПÑÑÑпМа: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "ÐÑОбка загÑÑзкО: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "ÐевПзЌПжМП ÑПеЎОМОÑÑÑÑ Ñ Ð¿ÑПвайЎеÑПЌ ОлО ÑÑÑв ÑПеЎОМеМОÑ, ÑлеЎÑÑÑÐ°Ñ Ð¿ÐŸÐ¿ÑÑка ÑеÑез ÐŸÐŽÐœÑ ÐŒÐžÐœÑÑÑ." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "ÐагÑÑзка пÑПпÑÑеМа: %(name)s @ %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "ÐекПЎОÑПваМОе МаÑаÑП: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "ÐÑОбка ЎекПЎОÑПваМОÑ: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "ÐПвÑПÑÐœÐ°Ñ Ð¿ÐŸÐ¿ÑÑка %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "ÐПлÑÑеМОе ОМÑПÑЌаÑОО пП %(name)s завеÑÑОлПÑÑ ÐŸÑОбкПй | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "ÐÑОбка вÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ð·Ð°Ñ
ваÑПв: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "ÐÑОбка акÑОваÑОО %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "ÐеÑепПЎклÑÑеМОе Ме ÑЎалПÑÑ: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "СкÑÐžÐ¿Ñ Ð¿ÐµÑепПЎклÑÑÐµÐœÐžÑ ÐœÐµ МайЎеМ!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "ÐаÑОМаеЌ пеÑепПЎклÑÑеМОе" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "ÐÑОбка пÑО вÑпПлМеМОО ÑкÑОпÑа пеÑепПЎклÑÑеМОÑ" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "ÐеÑепПЎклÑÑеМП, МПвÑй IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Ðе Ñ
ваÑÐ°ÐµÑ ÐŒÐµÑÑа Ма ÑÑÑÑПйÑÑве." + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Ðе ÐŒÐŸÐ³Ñ Ð²ÐŸÐ¹ÑО Ñ ÑÑеÑМПй запОÑÑÑ %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "ÐепÑавОлÑМÑй паÑПлÑ" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "ÐÑÐµÐŒÑ %s ÐžÐŒÐµÐµÑ ÐœÐµÐ¿ÑавОлÑМÑй ÑПÑЌаÑ, ОÑпПлÑзÑйÑе ÑПÑÐŒÐ°Ñ 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "ÐеЎПÑÑаÑПÑМП ÑÑаÑÑОка в аккаÑМÑе %s, ÑлеЎÑÑÑÐ°Ñ Ð¿ÑПвеÑка ÑеÑез 30 ЌОМÑÑ" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "ÐÑÑек ÑÑПк ЎейÑÑÐ²ÐžÑ Ð°ÐºÐºÐ°ÑМÑа %s, ÑлеЎÑÑÑÐ°Ñ Ð¿ÑПвеÑка ÑеÑез 1 ÑаÑ" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "ÐПÑÑОгМÑÑ Ð»ÐžÐŒÐžÑ Ð·Ð°Ð³ÑÑзПк" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s ÐžÐŒÐµÐµÑ ÐœÐµ пÑавОлÑМÑй ÑаблПМ." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "ÐÑОбка ОЌпПÑÑа %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Ðе загÑÑжеМ МО ПЎОМ Оз ÑайлПбЌеММОкПв" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Ð ÑвПей ÑÑÑÑМПй запОÑО вклÑÑОÑе ПпÑÐžÑ 'direct Download'" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "СпОÑПк ÑÑÑлПк Ме ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑОÑеМ." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "УÑÑаМПвкО ÑÑеÑМПй запОÑО ÑÐŽÐ°Ð»ÐµÐœÑ Ð² ÑвÑзО Ñ ÐœÐŸÐ²ÑÐŒ ÑПÑЌаÑПЌ." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "ÐеПбÑ
ПЎОЌа авÑПÑОзаÑÐžÑ (ÐžÐŒÑ Ð¿ÐŸÐ»ÑзПваÑелÑ:паÑПлÑ)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "ÐПжалÑйÑÑа, ввеЎОÑе Ð²Ð°Ñ Ð°ÐºÐºÐ°ÑÐœÑ ÐŽÐ»Ñ %s ОлО ПÑклÑÑОÑÑ ÑÑÐŸÑ Ð¿Ð»Ð°Ð³ÐžÐœ" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "ÐайЎеМ HTML-кПЎ в Ñайле загÑÑзкО (%s)... ПÑОбка пеÑеМапÑавлеМОÑ? ÐагÑÑзка бÑÐŽÐµÑ Ð¿ÐµÑезапÑÑеМа." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Ѐайл вÑеЌеММП МеЎПÑÑÑпеМ" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: ПжОЎаМОе ÐŒÐµÐ¶ÐŽÑ Ð·Ð°Ð³ÑÑзкаЌО %d Ñек." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: ПжОЎаМОе каÑÑОМкО %d Ñек." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "ÐагÑÑжеММÑй Ñайл пÑÑÑ" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "ÐевеÑМÑй клÑÑ API" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: ÐÑÑалПÑÑ ÐœÐµÐŽÐŸÑÑаÑПÑМП ÑÑаÑОка" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "ТÑаÑОк закПМÑОлÑÑ" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Traffic Share (пÑÑÐŒÐ°Ñ Ð·Ð°Ð³ÑÑзка)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Уже ÐžÐŽÐµÑ Ð·Ð°Ð³ÑÑзка Ñ ÑÑПгП IP, жЎеЌ 60 ÑекÑМЎ" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "ÐепÑавОлÑМÑй кПЎ ОЎеМÑОÑОкаÑОО, загÑÑзка бÑÐŽÐµÑ Ð¿ÐµÑезапÑÑеМа" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: ÐÐµÑ ÑвПбПЎМПгП ÑлПÑа" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "ÐÐ»Ñ ÑÑПгП Ñайла МÑжеМ пÑеЌОÑÐŒ аккаÑМÑ" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "ÐÐŒÑ Ñайла ÑказаМП МевеÑМП" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "ÐÑОбка паÑаллелÑМПй загÑÑзкО, жЎеЌ 60 ÑекÑМЎ." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "ÐÑ
ПЎ Ме пÑПОзвеЎеМ." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "СбПй ÑаÑÑОÑÑПвкО" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "ÐÐµÑ ÐºÐ»ÑÑа Ñайла в URL-аЎÑеÑе" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "ÐПЎ ПÑОбкО:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Ѐайл Ме ÑÑÑеÑÑвÑеÑ." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** ÐÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÑ, пеÑезапÑÑÑОÑе pyLoad ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "ÐÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÑ Ðž пеÑезагÑÑжеМÑ" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "ÐÐµÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐ¹" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "ÐÐµÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÐ¹ pyLoad" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** ÐПÑÑÑпМа ÐœÐŸÐ²Ð°Ñ Ð²ÐµÑÑÐžÑ pyLoad %s ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** СкаÑайÑе зЎеÑÑ: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Ðе вПзЌПжМП ÑПеЎОМОÑÑÑÑ Ñ ÑеÑвеÑПЌ ПбМПвлеМОй" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "ÐÐŸÐ²Ð°Ñ Ð²ÐµÑÑÐžÑ %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "ÐÑОбка пÑО ПбМПвлеМОО %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "ÐПМÑÐ»ÐžÐºÑ Ð²ÐµÑÑОО" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "ÐагÑÑзка завеÑÑеМа: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "ÐПвÑй запÑÐŸÑ ÐºÐ°ÑÑОМкО: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "ÐÑÐ²ÐµÑ Ñ ÑекÑÑПЌ Ма каÑÑОМке %s" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "ÐПжалÑйÑÑа, ÑМаÑала ЎПбавÑÑе ÑÑеÑМÑÑ Ð·Ð°Ð¿ÐžÑÑ premium.to О пеÑезапÑÑÑОÑе pyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "ÐПбавлеМ %s Оз HotFolder" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "%s Ме ÑÑÑаМПвлеМ" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Ðе вПзЌПжМП акÑОвОÑПваÑÑ %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "ÐкÑОвОÑПваМ(a/П)" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Ðе акÑОвОÑПваМП ЎПпПлМеМОй ÐŽÐ»Ñ ÐžÐ·Ð²Ð»ÐµÑеМОÑ/ÑаÑпакПвкО" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "ÐÐ°ÐºÐµÑ %s пПÑÑавлеМ в ПÑеÑÐµÐŽÑ ÐŽÐ»Ñ Ð¿ÐŸÑлеЎÑÑÑегП ОзвлеÑеМОÑ/ÑаÑпакПвкО" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "ÐÑПвеÑка пакеÑа %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "ÐзвлеÑеМОе/ÑаÑпакПвка в %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "Ðе МайЎеМП ÑайлПв ÐŽÐ»Ñ ÐžÐ·Ð²Ð»ÐµÑеМОÑ" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "ОзвлекаеÑÑÑ/ÑаÑпакПвÑваеÑÑÑ" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "ÐаÑОÑеМП паÑПлеЌ" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "ÐепÑавОлÑМÑй паÑПлÑ" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "УЎалеМОе ÑайлПв %s" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "ÐзвлеÑеМОe/ÑаÑпакПвка завеÑÑеМП(a)" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "ÐÑОбка аÑÑ
Ова" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "ÐÑОбка кПМÑÑПлÑМПй ÑÑЌЌÑ" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "ÐеОзвеÑÑÐœÐ°Ñ ÐŸÑОбка" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "ÐÑОбка ÑÑÑаМПвкО пПлÑзПваÑÐµÐ»Ñ Ðž гÑÑппÑ: %s" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: ÐПÑÑ 9666 Ñже заМÑÑ" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "ÐÑÑалПÑÑ %s кÑеЎОÑПв" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Ðе ÑЎалПÑÑ ÐŸÑпÑавОÑÑ ÐŸÑвеÑ." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "ÐеЎПÑÑаÑПÑМП ÑÑеЎÑÑв Ма ваÑеЌ аккаÑМÑе CaptchaTrader" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "СпОÑПк ÑОÑÑÐŸÐ²Ð°ÐœÐžÑ ÐœÐµ МайЎеМ" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "СпОÑПк ÑОÑÑÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÑÑ" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "ÐагÑÑзка завеÑÑеМа: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "ÐПваÑ(Ñе) CaptchaID Оз загÑÑзкО: %s: %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "ÐаÑа ÑÑеÑÐœÐ°Ñ Ð·Ð°Ð¿ÐžÑÑ 9kw.eu ÐžÐŒÐµÐµÑ ÐœÐµ ЎПÑÑаÑПÑМП кÑеЎОÑПв" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "УÑÑаМПвлеММÑе ÑкÑОпÑÑ ÐŽÐ»Ñ %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Ðе вПзЌПжМП запÑÑÑОÑÑ ÑкÑОпÑ:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "ÐÑОбка в %(script): %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "УÑеÑÐœÐ°Ñ Ð·Ð°Ð¿ÐžÑÑ ExpertDecoders Ме ÐžÐŒÐµÐµÑ ÐŽÐŸÑÑаÑПÑМП кÑеЎОÑПв" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "ÐПжалÑйÑÑа ÑМаÑала ЎПбавÑÑе Ð²Ð°Ñ rehost.to аккаÑÐœÑ Ðž пеÑезапÑÑÑОÑе pyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "ÐПжалÑйÑÑа ÑМаÑала ЎПбавÑÑе ЎейÑÑвОÑелÑМÑÑ ÑÑеÑМÑÑ Ð·Ð°Ð¿ÐžÑÑ ÐŽÐ»Ñ premiumize.me О пеÑезапÑÑÑОÑÑ pyLoad." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "ÐÑÑалПÑÑ %s кÑеЎОÑПв" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil О tesseract Ме ÑÑÑаМПвлеМÑ. Ðе пПЎклÑÑеМ ÐºÐ»ÐžÐµÐœÑ ÐŽÐ»Ñ ÑаÑÑОÑÑПвкО каÑÑОМПк" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Ðе пПлÑÑеМ ÑезÑлÑÑÐ°Ñ ÑаÑÑОÑÑПвкО каÑÑОМкО в ÑеÑеМОе ПÑвеЎÑММПгП вÑеЌеМО МО ПЎМОЌ Оз ЎПпПлМеМОй" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "ÐÑОбка ÑÑÑаМПвкО пПлÑзПваÑÐµÐ»Ñ Ðž гÑÑппÑ: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Ðе пПЎклÑÑеМ ÐºÐ»ÐžÐµÐœÑ ÐŽÐ»Ñ ÑаÑÑОÑÑПвкО каÑÑОМПк" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "ÐПбавлеМ кПМÑÐµÐ¹ÐœÐµÑ %(name)s Ñ %(count)d ÑÑлкаЌО" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "ÐПбавлеМП %(count)d ÑÑÑлПк в кПМÑÐµÐ¹ÐœÐµÑ #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Ðе ПбМаÑÑжеМа js плаÑÑПÑЌа, пПжалÑйÑÑа ÑÑÑаМПвОÑе лОбП Spidermonkey, ossp-js, pyv8 ОлО rhino" + diff --git a/locale/ru/LC_MESSAGES/pyLoadCli.mo b/locale/ru/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index adbb5e141..000000000 --- a/locale/ru/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/ru/LC_MESSAGES/pyLoadCli.po b/locale/ru/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..61d91a9fb --- /dev/null +++ b/locale/ru/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Russian\n" +"Language: ru_RU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "ÐМÑеÑÑÐµÐ¹Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑПкО" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s загÑÑзПк:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "СкПÑПÑÑÑ: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "РазЌеÑ: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "ÐакПМÑеМП в: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "ПжОЎаМОе: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "СПÑÑПÑМОе:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "пÑОПÑÑаМПвлеМП" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "в пÑПÑеÑÑе" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "ПбÑÐ°Ñ ÑкПÑПÑÑÑ" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "ЀайлПв в ПÑеÑеЎО" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "ÐÑегП" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "ÐеМÑ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "ÐПбавОÑÑ ÑÑÑлкО" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "УпÑавлеМОе ПÑеÑеЎÑÑ" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "УпÑавлеМОе кПллекÑПÑПЌ ÑÑÑлПк" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "ÐапÑÑÑОÑÑ/ÐÑОПÑÑаМПвОÑÑ ÑеÑвеÑ" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "ÐÑÑаМПвОÑÑ ÑеÑвеÑ" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "ÐÑÑ
ПЎ" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "ÐÑпПлÑзÑйÑе ÑаблПМ: add <ÐÐŒÑ ÐºÐŸÐœÑейМеÑа> <ÑÑÑлка1> <ÑÑÑлка2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "ÐÑПвеÑка %d ÑÑÑлкО:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Ѐайл Ме МайЎеМ." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "РабПÑа pyLoad бÑла пÑОМÑЎОÑелÑМП завеÑÑеМа" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "ÐПказаÑÑ ÑПÑÑПÑМОе ÑеÑвеÑа" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "ÐПказаÑÑ Ð·Ð°ÐºÐ°ÑкО в ПÑеÑеЎО" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "ÐПказаÑÑ Ð·Ð°ÐºÐ°ÑкО в ÑпОÑке кПллекÑПÑа" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "ÐПбавОÑÑ ÐºÐŸÐœÑÐµÐ¹ÐœÐµÑ Ð² ПÑеÑеЎÑ" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "ÐПбавлÑÐµÑ ÐºÐŸÐœÑÐµÐ¹ÐœÐµÑ Ð² кПллекÑÐŸÑ ÑÑÑлПк" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "УЎалОÑÑ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ПÑеÑеЎО/кПллекÑПÑа" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "УЎалОÑÑ ÐºÐŸÐœÑÐµÐ¹ÐœÐµÑ ÐžÐ· ПÑеÑеЎО/кПллекÑПÑа" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "ÐеÑеЌеÑÑОÑÑ Ð¿Ð°ÐºÐµÑ(Ñ) Оз ПÑеÑеЎО в кПллекÑÐŸÑ Ðž МаПбПÑПÑ" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "ÐеÑезапÑÑÑОÑÑ ÑайлÑ" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "ÐеÑезапÑÑÑОÑÑ Ð¿Ð°ÐºÐµÑÑ" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "ÐÑПвеÑка ÑÑаÑÑÑа ÑвÑзО, ЎейÑÑвÑÐµÑ Ñ ÐŒÐµÑÑМÑЌО кПМÑейМеÑаЌО" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "ÐÑПвеÑÑÐµÑ ÑПÑÑПÑМОе Ñайла-кПМÑейМеÑа" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "ÐÑОПÑÑаМПвОÑÑ ÑеÑвеÑ" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "пÑПЎПлжОÑÑ Ð·Ð°ÐºÐ°ÑкО" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "ÐеÑеклÑÑОÑÑ Ð¿Ð°Ñза/пÑПЎПлжОÑÑ" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "ПÑÑаМПвОÑÑ ÑеÑвеÑ" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "СпОÑПк кПЌаМЎ: " + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "ÐапОÑаÑÑ Ñайл кПМÑОгÑÑаÑОО пПлÑзПваÑÐµÐ»Ñ ÐœÐµ ÑЎалПÑÑ" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "ÐÐ»Ñ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÑ Ñ ÑÐŽÑПЌ pyLoad МеПбÑ
ПЎОЌ Ð¿Ð°ÐºÐµÑ py-openssl." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "ÐÐŽÑеÑ: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "ÐПÑÑ: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "ÐÐŒÑ Ð¿ÐŸÐ»ÑзПваÑелÑ: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "ÐаÑПлÑ: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "ÐепÑавОлÑМÑе ÑÑÑÑМÑе ЎаММÑе." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "ÐевПзЌПжМП пПЎклÑÑОÑÑÑÑ Ðº %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "ÐÐ»Ñ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÑ Ñ ÑÐŽÑПЌ pyLoad МеПбÑ
ПЎОЌ Ð¿Ð°ÐºÐµÑ py-openssl." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Ð ÑвÑзО Ñ ÑеЌ, ÑÑП бÑлО Ð²Ð²ÐµÐŽÐµÐœÑ ÑÑÐŽ кПЌаМЎ, ОМÑеÑакÑОвМÑй ÑежОЌ бÑл пÑеÑваМ." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "ÐПбавОÑÑ Ð¿Ð°ÐºÐµÑ:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "ÐвеЎОÑе МазваМОе пакеÑа" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "ÐПМÑейМеÑ: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "ÐМалОз ÑÑÑлПк ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "ÐвеЎОÑе %s кПгЎа бÑЎеÑе гПÑПвÑ." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ ÑÑÑлкО: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "МазаЎ в главМПе ЌеМÑ" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "УпÑавлеМОе пакеÑаЌО:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "УпÑавлеМОе ÑÑÑлкаЌО" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "ЧÑП ÐÑ Ñ
ПÑОÑе пеÑеЌеÑÑОÑÑ?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "ЧÑП ÐÑ Ñ
ПÑОÑе ÑЎалОÑÑ?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "ЧÑП ÐÑ Ñ
ПÑОÑе пеÑезапÑÑÑОÑÑ?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "ÐÑбОÑайÑе, ÑÑП ÐÑ Ñ
ПÑОÑе ÑЎелаÑÑ ÐžÐ»Ðž вМеÑОÑе ÐœÐŸÐŒÐµÑ Ð¿Ð°ÐºÐµÑа." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "ÑЎалОÑÑ" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "пеÑеЌеÑÑОÑÑ" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "пеÑезапÑÑÑОÑÑ" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "- пÑеЎÑÐŽÑÑОй" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "- ÑлеЎÑÑÑОй" + diff --git a/locale/ru/LC_MESSAGES/pyLoadGui.mo b/locale/ru/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 11d4328c0..000000000 --- a/locale/ru/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/ru/LC_MESSAGES/setup.mo b/locale/ru/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index fb1201628..000000000 --- a/locale/ru/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/ru/LC_MESSAGES/setup.po b/locale/ru/LC_MESSAGES/setup.po new file mode 100644 index 000000000..e55aa5fe7 --- /dev/null +++ b/locale/ru/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Russian\n" +"Language: ru_RU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "Ўа" + +#: module/setup.py:53 +msgid "n" +msgstr "МеÑ" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "ÐÐ°Ñ Ð¿ÑОвеÑÑÑвÑÐµÑ Ð¿ÐŸÐŒÐŸÑМОк пП МаÑÑÑПйке pyLoad" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "ÐÑÐŽÐµÑ Ð¿ÑПвеÑеМа ÑОÑÑеЌа О вМеÑÐµÐœÑ Ð¿ÐµÑвПМаÑалÑМÑе МаÑÑÑПйкО ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÑка pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "РкваЎÑаÑМÑÑ
ÑкПбкаÑ
[] ÑказÑваÑÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸ ÑЌПлÑаМОÑ," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "еÑлО ÐÑ ÐœÐµ Ñ
ПÑОÑе ЌеМÑÑÑ ÑÑО зМаÑÐµÐœÐžÑ ÐžÐ»Ðž Ме ÑвеÑÐµÐœÑ Ð² ÑвПÑÐŒ вÑбПÑе, пÑПÑÑП МажЌОÑе ENTER." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Ðе забÑÐŽÑÑе: ÐÑ Ð²ÑегЎа ЌПжеÑе ÑМПва запÑÑÑОÑÑ Ð¿ÐŸÐŒÐŸÑМОка пП МаÑÑÑПйкаЌ, МабÑав pyload.py Ñ ÐºÐ»ÑÑПЌ --setup ОлО -s." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "ÐÑО вПзМОкМПвеМОО пÑПблеЌ Ñ ÑÑОЌ аÑÑОÑÑеМÑПЌ МажЌОÑе STRG-C" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "ÐŽÐ»Ñ Ð¿ÑекÑаÑÐµÐœÐžÑ ÑÑÑаМПвкО. pyload.py бПлÑÑе Ме бÑÐŽÐµÑ Ð·Ð°Ð¿ÑÑкаÑÑÑÑ Ð°Ð²ÑПЌаÑОÑеÑкО." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "ÐÐ»Ñ ÑÑаÑÑа пÑПвеÑкО ÑОÑÑеЌÑ, МажЌОÑе ENTER." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "ÐÐ»Ñ ÑабПÑÑ pyLoad МеПбÑ
ÐŸÐŽÐžÐŒÑ pycurl, sqlite О python 2.5, 2.6, 2.7." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "УÑÑаМПвОÑе МеЎПÑÑаÑÑОе пакеÑÑ Ðž пеÑезапÑÑÑОÑе pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "ÐÑПгÑаЌЌа ÑÑÑаМПвкО завеÑÑÐ°ÐµÑ ÑабПÑÑ." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "ÐÑПвеÑка ÑОÑÑÐµÐŒÑ Ð·Ð°Ð²ÐµÑÑеМа. ЧÑÐŸÐ±Ñ Ð¿ÑПÑЌПÑÑеÑÑ ÐŸÑÑеÑ, МажЌОÑе клавОÑÑ ENTER." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## ÐÑÑÐµÑ ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "ÑаÑÑОÑÑПвка" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "SSL пПЎклÑÑеМОе" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "авÑПЌаÑОÑеÑÐºÐ°Ñ ÑаÑÑОÑÑПвка CAPTCHA" + +#: module/setup.py:104 +msgid "GUI" +msgstr "GUI " + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Web-ОМÑеÑÑейÑ" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "пПЎЎеÑжка Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "ÐПÑÑÑпМÑе ÑÑМкÑОО:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "ÐеЎПÑÑÑпМÑе ÑÑМкÑОО:" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "МеЎПÑÑÑпеМ py-crypto" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "ÐМ МÑжеМ ÐŽÐ»Ñ ÑаÑкПЎОÑÐŸÐ²Ð°ÐœÐžÑ ÑайлПв." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "ÐœÐµÑ SSL" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "ÐМ МÑжеМ ÐŽÐ»Ñ Ð·Ð°ÑОÑÑ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÑ Ñ ÑÐŽÑПЌ ОлО web-ОМÑеÑÑейÑПЌ." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "ÐÑО лПкалÑМÑÑ
ÑПеЎОМеМОÑÑ
SSL Ме МÑжеМ." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "РаÑÑОÑÑПвка Captcha МеЎПÑÑÑпМа" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "ÐÑжМа Ма МекПÑПÑÑÑ
Ñайл-Ñ
ПÑÑОМгаÑ
." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "ÐÐµÑ GUI" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "ÐÐµÑ Ð¿ÐŸÐŽÐŽÐµÑжкО JavaScript" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "ÐÑП пПМаЎПбОÑÑÑÑ ÐŽÐ»Ñ ÐœÐµÐºÐŸÑПÑÑÑ
ÑÑÑлПк Click'N'Load. ÐМÑÑалОÑПвайÑе Spidermonkey, ossp-js, pyv8 ОлО rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "ÐÑО желаМОО ÑейÑÐ°Ñ ÐŒÐŸÐ¶ÐœÐŸ пÑеÑваÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ Ðž пПÑÑавОÑÑ ÐœÐµÐŸÐ±Ñ
ПЎОЌÑе завОÑОЌÑе пакеÑÑ." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "ÐÑПЎПлжОÑÑ ÐœÐ°ÑÑÑПйкÑ?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "ÐÑжМП лО ЌеМÑÑÑ Ð¿ÑÑÑ Ðº папке МаÑÑÑПек? ТекÑÑОй пÑÑÑ %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "ÐÑлО Ð²Ñ ÐžÑпПлÑзÑеÑе pyLoad Ма какПЌ-МОбÑÐŽÑ ÑеÑвеÑе ОлО пÑÑÑ Ðº кПМÑОгÑÑаÑОО ÑказÑÐ²Ð°ÐµÑ ÐœÐ° flash-ЎОÑк, лÑÑÑе пПЌеМÑйÑе егП." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "ÐзЌеМОÑÑ Ð¿ÑÑÑ?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "ХПÑОÑе ОзЌеМОÑÑ ÑÑÑÑМÑе ЎаММÑе О ÐŽÑÑгОе базПвÑе МаÑÑÑПйкО?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "ÐаÑÑПÑÑелÑМП ÑекПЌеМЎÑеÑÑÑ Ð¿ÑО пеÑвПЌ запÑÑке." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "ÐзЌеМОÑÑ ÐŸÑМПвМÑе МаÑÑÑПйкО?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "ХПÑОÑе МаÑÑÑПОÑÑ SSL?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "ÐаÑÑÑПОÑÑ SSL?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "ХПÑОÑе МаÑÑÑПОÑÑ WEB-ОМÑеÑÑейÑ?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "ÐаÑÑÑПОÑÑ WEB-ОМÑеÑÑейÑ?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "УÑÑаМПвка ÑÑпеÑМП завеÑÑеМа." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "ÐажЌОÑе ENTER О запÑÑÑОÑе pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## ÐÑПвеÑка ÑОÑÑÐµÐŒÑ ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "ÐеÑÑÐžÑ python ÑлОÑкПЌ МПваÑ, ОÑпПлÑзÑйÑе Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "ÐеÑÑÐžÑ python ÑлОÑкПЌ ÑÑаÑаÑ, ОÑпПлÑзÑйÑе Python веÑÑОО 2.5 О вÑÑе" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "ÐеÑÑÐžÑ Python: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "СлОÑкПЌ ÑÑаÑÐ°Ñ Ð²ÐµÑÑÐžÑ jinja2 %s." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "ÐПжМП ÑпПкПйМП пÑПЎПлжОÑÑ ÐœÐ°ÑÑÑПйкÑ, МП еÑлО web-ОМÑеÑÑÐµÐ¹Ñ ÐœÐµ бÑÐŽÐµÑ ÑабПÑаÑÑ," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "ÑП ПбМПвОÑе ОлО ÑЎалОÑе бОблОПÑÐµÐºÑ jinja2. ÐМа Ñже еÑÑÑ Ð² ÑПÑÑаве pyLoad." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## ÐÑМПвМÑе МаÑÑÑПйкО ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "ÐÑО ÑÑÑÑМÑе ЎаММÑе пПЎÑ
ПЎÑÑ Ðº CLI, GUI О WEB-ОМÑеÑÑейÑÑ." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "ÐПлÑзПваÑелÑ" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "ÐМеÑМОЌ клОеМÑаЌ (GUI, CLI О ÐŽÑÑгОе) пПМаЎПбОÑÑÑÑ ÐŽÐžÑÑаМÑОПММÑй ЎПÑÑÑп ÐŽÐ»Ñ ÑабПÑÑ ÑеÑез ÑеÑÑ." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "ÐÑлО ÐÑ Ñ
ПÑОÑе пПлÑзПваÑÑÑÑ ÑПлÑкП ÑПеЎОМеМОеЌ ÑеÑез веб ОМÑеÑÑейÑ, ПÑклÑÑОÑе егП, ÑÑÐŸÐ±Ñ ÑЌеМÑÑОÑÑ Ð¿ÐŸÑÑеблеМОе ПпеÑаÑОвМПй паЌÑÑО." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "ÐклÑÑОÑÑ ÐŽÐžÑÑаМÑОПММÑй ЎПÑÑÑп" + +#: module/setup.py:291 +msgid "Language" +msgstr "ЯзÑк" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "Ðапка закаÑек" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "ÐакÑ.ÑОÑлП ПЎМПвÑеЌеММÑÑ
закаÑек" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "ÐÑпПлÑзПваÑÑ Ð¿ÐµÑепПЎклÑÑеМОе ОМÑеÑМеÑа?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "ÐÑÑÑ Ðº ÑкÑОпÑÑ Ð¿ÐµÑепПЎклÑÑеМОÑ" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## УÑÑаМПвкО WEB-ОМÑеÑÑейÑа ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "ÐклÑÑОÑÑ WEB-ОМÑеÑÑейÑ?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "ip-аЎÑÐµÑ WEB-ОМÑеÑÑейÑа. ÐÑлО ÑказаÑÑ 127.0.0.1 ОлО localhost, ÑП WEB-ОМÑеÑÑÐµÐ¹Ñ Ð±ÑÐŽÐµÑ ÐŽÐŸÑÑÑпеМ ÑПлÑкП лПкалÑМП." + +#: module/setup.py:312 +msgid "Address" +msgstr "ÐÐŽÑеÑ" + +#: module/setup.py:313 +msgid "Port" +msgstr "ÐПÑÑ" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "Ð pyLoad МеÑкПлÑкП влПжеММÑÑ
ÑеÑвеÑПв, МОже ÑлеЎÑÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ Ð² кПÑПÑкПЌ вОЎе." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "СÑаМЎаÑÑÐœÐ°Ñ ÐœÐ°ÑÑÑПйка, МаОлÑÑÑОй вÑÐ±ÐŸÑ ÐµÑлО ваЌ Ме ÑÑМП какПй ÑЎелаÑÑ Ð²ÑбПÑ." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "ÐÑÐŸÑ ÑеÑÐ²ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ SSL О Ñ
ПÑПÑаÑ, Ð³ÐŸÐŽÐœÐ°Ñ Ð°Ð»ÑÑеÑМаÑОва к builtin." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "ÐÐŸÐ¶ÐµÑ ÐžÑпПлÑзПваÑÑÑÑ Ð²ÐŒÐµÑÑе Ñ apache, lighttpd, ÑÑебÑÐµÑ ÐœÐ°ÑÑÑПйкО, ÑÑП ÑвлÑеÑÑÑ ÐœÐµ ÑакОЌ пÑПÑÑÑÐŒ заЎаМОеЌ." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "ÐПлÑÑОÑÑ ÐµÐ³ÐŸ зЎеÑÑ: https://github.com/jonashaag/bjoern О ÑкПЌпОлОÑПваÑÑ ÐµÐ³ÐŸ" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "ÐМОЌаМОе: РМекПÑПÑÑÑ
ÑеЎкОÑ
ÑлÑÑаÑÑ
вÑÑÑПеММÑй ÑеÑÐ²ÐµÑ ÐœÐµ ÑабПÑаеÑ, еÑлО Ð²Ñ Ð·Ð°ÐŒÐµÑОлО пÑÐŸÐ±Ð»ÐµÐŒÑ Ñ Ð²ÐµÐ±-ОМÑеÑÑейÑПЌ" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "веÑМÑÑÑÑÑ ÑÑЎа О ОзЌеМОÑÑ ÑеÑÐ²ÐµÑ builtin Ма ÑеÑÐ²ÐµÑ threaded." + +#: module/setup.py:329 +msgid "Server" +msgstr "СеÑвеÑ" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## ÐаÑÑÑПйкО SSL ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "ÐÐ»Ñ Ð³ÐµÐœÐµÑаÑОО SSL ÑеÑÑОÑОкаÑПв вÑпПлМОÑе ÑлеЎÑÑÑОе кПЌаМЎÑ, МаÑ
ПЎÑÑÑ Ð² папке кПМÑОгÑÑаÑОО pyLoad:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "ÐÑлО вÑÑ Ð¿ÑПÑлП ÑÑпеÑМП, ÑейÑÐ°Ñ ÐŒÐŸÐ¶ÐœÐŸ бÑÐŽÐµÑ Ð²ÐºÐ»ÑÑОÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ SSL." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "ÐклÑÑОÑÑ SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "ÐÑбеÑОÑе ЎейÑÑвОе" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - ÐПбавОÑÑ/ÐзЌеМОÑÑ Ð¿ÐŸÐ»ÑзПваÑелÑ" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - ÐПказаÑÑ ÑпОÑПк пПлÑзПваÑелей" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - УЎалОÑÑ Ð¿ÐŸÐ»ÑзПваÑелÑ" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - ÐÑÑ
ПЎ" + +#: module/setup.py:376 +msgid "Users" +msgstr "ÐПлÑзПваÑелО" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "УÑÑаМПвлеМ МПвÑй пÑÑÑ Ðº папке МаÑÑÑПек. ТекÑÑОе МаÑÑÑПйкО Ме бÑÐŽÑÑ ÑПÑ
ÑаМеМÑ!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "ÐÑÑÑ Ðº МаÑÑÑПйкаЌ" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "ÐÑÑÑ Ðº МаÑÑÑПйкаЌ бÑл ОзЌеМÑМ. ÐеÑезапÑÑÑОÑе аÑÑОÑÑÐµÐœÑ ÐŽÐ»Ñ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐµÐœÐžÑ ÐœÐ°ÑÑÑПйкО." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "ÐажЌОÑе клавОÑÑ Enter ÐŽÐ»Ñ Ð²ÑÑ
ПЎа." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Ðе ÑЎалПÑÑ ÑÑÑаМПвОÑÑ Ð¿ÑÑÑ Ðº МаÑÑÑПйкаЌ: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: ПÑÑÑÑÑÑвÑеÑ" + +#: module/setup.py:464 +msgid "Password: " +msgstr "ÐаÑПлÑ: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "СлОÑкПЌ пÑПÑÑПй паÑПлÑ, МÑжМП ЌОМОЌÑÐŒ 4 ÑОЌвПла." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "ÐаÑÐŸÐ»Ñ (ÐПвÑПÑОÑÑ)" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "ÐаÑПлО Ме ÑПвпаЎаÑÑ." + +#: module/setup.py:493 +msgid "yes" +msgstr "Ўа" + +#: module/setup.py:493 +msgid "true" +msgstr "Ðа" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "МеÑ" + +#: module/setup.py:496 +msgid "false" +msgstr "ÐПжÑ" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "ÐекПÑÑекÑМÑй ввПЎ" + diff --git a/locale/setup.pot b/locale/setup.pot index cf4dd8cfc..11d64d094 100644 --- a/locale/setup.pot +++ b/locale/setup.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: pyLoad 0.4.9\n" +"Project-Id-Version: pyLoad 0.4.10\n" "Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" -"POT-Creation-Date: 2011-12-07 19:21+0100\n" +"POT-Creation-Date: 2014-07-13 20:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,479 +17,463 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: module/setup.py:51 +#: module/setup.py:33 msgid "y" msgstr "" -#: module/setup.py:53 +#: module/setup.py:35 msgid "n" msgstr "" -#: module/setup.py:72 -msgid "Welcome to the pyLoad Configuration Assistent." +#: module/setup.py:53 +msgid "Welcome to the pyLoad Configuration Assistant." msgstr "" -#: module/setup.py:73 +#: module/setup.py:54 msgid "" "It will check your system and make a basic setup in order to run pyLoad." msgstr "" -#: module/setup.py:75 +#: module/setup.py:56 msgid "The value in brackets [] always is the default value," msgstr "" -#: module/setup.py:76 +#: module/setup.py:57 msgid "" "in case you don't want to change it or you are unsure what to choose, just " "hit enter." msgstr "" -#: module/setup.py:77 +#: module/setup.py:59 msgid "" -"Don't forget: You can always rerun this assistent with --setup or -s " -"parameter, when you start pyLoadCore." +"Don't forget: You can always rerun this assistant with --setup or -s " +"parameter, when you start pyload.py ." msgstr "" -#: module/setup.py:78 -msgid "If you have any problems with this assistent hit STRG-C," +#: module/setup.py:60 +msgid "If you have any problems with this assistant hit STRG-C," msgstr "" -#: module/setup.py:79 -msgid "to abort and don't let him start with pyLoadCore automatically anymore." +#: module/setup.py:61 +msgid "to abort and don't let him start with pyload.py automatically anymore." msgstr "" -#: module/setup.py:81 +#: module/setup.py:63 msgid "When you are ready for system check, hit enter." msgstr "" -#: module/setup.py:88 +#: module/setup.py:70 msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." msgstr "" -#: module/setup.py:89 +#: module/setup.py:71 msgid "Please correct this and re-run pyLoad." msgstr "" -#: module/setup.py:90 +#: module/setup.py:72 msgid "Setup will now close." msgstr "" -#: module/setup.py:94 +#: module/setup.py:76 msgid "System check finished, hit enter to see your status report." msgstr "" -#: module/setup.py:96 +#: module/setup.py:78 msgid "## Status ##" msgstr "" -#: module/setup.py:101 +#: module/setup.py:83 msgid "container decrypting" msgstr "" -#: module/setup.py:102 +#: module/setup.py:85 msgid "ssl connection" msgstr "" -#: module/setup.py:103 +#: module/setup.py:87 msgid "automatic captcha decryption" msgstr "" -#: module/setup.py:104 -msgid "GUI" -msgstr "" - -#: module/setup.py:105 +#: module/setup.py:89 msgid "Webinterface" msgstr "" -#: module/setup.py:106 +#: module/setup.py:91 msgid "extended Click'N'Load" msgstr "" -#: module/setup.py:113 +#: module/setup.py:98 msgid "Features available:" msgstr "" -#: module/setup.py:117 +#: module/setup.py:102 msgid "Featues missing: " msgstr "" -#: module/setup.py:121 +#: module/setup.py:106 msgid "no py-crypto available" msgstr "" -#: module/setup.py:122 +#: module/setup.py:107 msgid "You need this if you want to decrypt container files." msgstr "" -#: module/setup.py:126 +#: module/setup.py:111 msgid "no SSL available" msgstr "" -#: module/setup.py:127 +#: module/setup.py:112 msgid "" "This is needed if you want to establish a secure connection to core or " "webinterface." msgstr "" -#: module/setup.py:128 +#: module/setup.py:113 msgid "If you only want to access locally to pyLoad ssl is not usefull." msgstr "" -#: module/setup.py:132 +#: module/setup.py:117 msgid "no Captcha Recognition available" msgstr "" -#: module/setup.py:133 +#: module/setup.py:118 msgid "Only needed for some hosters and as freeuser." msgstr "" -#: module/setup.py:137 -msgid "Gui not available" -msgstr "" - -#: module/setup.py:138 -msgid "The Graphical User Interface." -msgstr "" - -#: module/setup.py:142 +#: module/setup.py:122 msgid "no JavaScript engine found" msgstr "" -#: module/setup.py:143 +#: module/setup.py:123 msgid "" "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-" "js, pyv8 or rhino" msgstr "" -#: module/setup.py:145 +#: module/setup.py:125 msgid "You can abort the setup now and fix some dependicies if you want." msgstr "" -#: module/setup.py:147 +#: module/setup.py:127 msgid "Continue with setup?" msgstr "" -#: module/setup.py:153 +#: module/setup.py:133 #, python-format msgid "Do you want to change the config path? Current is %s" msgstr "" -#: module/setup.py:154 +#: module/setup.py:135 msgid "" "If you use pyLoad on a server or the home partition lives on an iternal " "flash it may be a good idea to change it." msgstr "" -#: module/setup.py:155 +#: module/setup.py:136 msgid "Change config path?" msgstr "" -#: module/setup.py:162 +#: module/setup.py:142 msgid "Do you want to configure login data and basic settings?" msgstr "" -#: module/setup.py:163 +#: module/setup.py:143 msgid "This is recommend for first run." msgstr "" -#: module/setup.py:164 +#: module/setup.py:144 msgid "Make basic setup?" msgstr "" -#: module/setup.py:171 +#: module/setup.py:151 msgid "Do you want to configure ssl?" msgstr "" -#: module/setup.py:172 +#: module/setup.py:152 msgid "Configure ssl?" msgstr "" -#: module/setup.py:178 +#: module/setup.py:158 msgid "Do you want to configure webinterface?" msgstr "" -#: module/setup.py:179 +#: module/setup.py:159 msgid "Configure webinterface?" msgstr "" -#: module/setup.py:184 +#: module/setup.py:164 msgid "Setup finished successfully." msgstr "" -#: module/setup.py:185 +#: module/setup.py:165 msgid "Hit enter to exit and restart pyLoad" msgstr "" -#: module/setup.py:191 +#: module/setup.py:172 msgid "## System Check ##" msgstr "" -#: module/setup.py:196 +#: module/setup.py:175 msgid "Your python version is to new, Please use Python 2.6/2.7" msgstr "" -#: module/setup.py:199 +#: module/setup.py:178 msgid "Your python version is to old, Please use at least Python 2.5" msgstr "" -#: module/setup.py:202 +#: module/setup.py:181 msgid "Python Version: OK" msgstr "" -#: module/setup.py:249 +#: module/setup.py:224 #, python-format msgid "Your installed jinja2 version %s seems too old." msgstr "" -#: module/setup.py:250 +#: module/setup.py:225 msgid "You can safely continue but if the webinterface is not working," msgstr "" -#: module/setup.py:251 +#: module/setup.py:226 msgid "" "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." msgstr "" -#: module/setup.py:268 +#: module/setup.py:243 msgid "JS engine" msgstr "" -#: module/setup.py:274 +#: module/setup.py:250 msgid "## Basic Setup ##" msgstr "" -#: module/setup.py:277 -msgid "The following logindata is valid for CLI, GUI and webinterface." +#: module/setup.py:253 +msgid "The following logindata is valid for CLI and webinterface." msgstr "" -#: module/setup.py:282 module/setup.py:371 module/setup.py:387 +#: module/setup.py:259 module/setup.py:357 module/setup.py:373 msgid "Username" msgstr "" -#: module/setup.py:288 +#: module/setup.py:265 msgid "" "External clients (GUI, CLI or other) need remote access to work over the " "network." msgstr "" -#: module/setup.py:289 +#: module/setup.py:266 msgid "" "However, if you only want to use the webinterface you may disable it to save " "ram." msgstr "" -#: module/setup.py:290 +#: module/setup.py:267 msgid "Enable remote access" msgstr "" -#: module/setup.py:295 +#: module/setup.py:271 msgid "Language" msgstr "" -#: module/setup.py:298 +#: module/setup.py:273 msgid "Downloadfolder" msgstr "" -#: module/setup.py:299 +#: module/setup.py:274 msgid "Max parallel downloads" msgstr "" -#: module/setup.py:303 +#: module/setup.py:278 msgid "Use Reconnect?" msgstr "" -#: module/setup.py:306 +#: module/setup.py:281 msgid "Reconnect script location" msgstr "" -#: module/setup.py:311 +#: module/setup.py:286 msgid "## Webinterface Setup ##" msgstr "" -#: module/setup.py:314 +#: module/setup.py:289 msgid "Activate webinterface?" msgstr "" -#: module/setup.py:316 +#: module/setup.py:291 msgid "" "Listen address, if you use 127.0.0.1 or localhost, the webinterface will " "only accessible locally." msgstr "" -#: module/setup.py:317 +#: module/setup.py:292 msgid "Address" msgstr "" -#: module/setup.py:318 +#: module/setup.py:293 msgid "Port" msgstr "" -#: module/setup.py:320 +#: module/setup.py:295 msgid "" "pyLoad offers several server backends, now following a short explanation." msgstr "" -#: module/setup.py:321 -msgid "Default server, best choice if you dont know which one to choose." -msgstr "" - -#: module/setup.py:322 -msgid "This server offers SSL and is a good alternative to builtin." +#: module/setup.py:296 +msgid "Default server; best choice if you plan to use pyLoad just for you." msgstr "" -#: module/setup.py:323 +#: module/setup.py:297 msgid "" -"Can be used by apache, lighttpd, requires you to configure them, which is " -"not too easy job." +"Support SSL connection and can serve simultaneously more client flawlessly." msgstr "" -#: module/setup.py:324 -msgid "Very fast alternative written in C, requires libev and linux knowlegde." -msgstr "" - -#: module/setup.py:325 -msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +#: module/setup.py:299 +msgid "" +"Can be used by apache, lighttpd, etc.; needs to be properly configured " +"before." msgstr "" -#: module/setup.py:326 -msgid "and copy bjoern.so to module/lib" +#: module/setup.py:301 +msgid "Very fast alternative to builtin; requires libev and bjoern packages." msgstr "" -#: module/setup.py:329 +#: module/setup.py:305 msgid "" "Attention: In some rare cases the builtin server is not working, if you " "notice problems with the webinterface" msgstr "" -#: module/setup.py:330 +#: module/setup.py:306 msgid "come back here and change the builtin server to the threaded one here." msgstr "" -#: module/setup.py:333 +#: module/setup.py:315 msgid "Server" msgstr "" -#: module/setup.py:337 +#: module/setup.py:320 msgid "## SSL Setup ##" msgstr "" -#: module/setup.py:339 +#: module/setup.py:322 msgid "" "Execute these commands from pyLoad config folder to make ssl certificates:" msgstr "" -#: module/setup.py:345 +#: module/setup.py:328 msgid "If you're done and everything went fine, you can activate ssl now." msgstr "" -#: module/setup.py:347 +#: module/setup.py:330 msgid "Activate SSL?" msgstr "" -#: module/setup.py:361 +#: module/setup.py:347 msgid "Select action" msgstr "" -#: module/setup.py:362 +#: module/setup.py:348 msgid "1 - Create/Edit user" msgstr "" -#: module/setup.py:363 +#: module/setup.py:349 msgid "2 - List users" msgstr "" -#: module/setup.py:364 +#: module/setup.py:350 msgid "3 - Remove user" msgstr "" -#: module/setup.py:365 +#: module/setup.py:351 msgid "4 - Quit" msgstr "" -#: module/setup.py:377 +#: module/setup.py:363 msgid "Users" msgstr "" -#: module/setup.py:406 +#: module/setup.py:391 msgid "Setting new configpath, current configuration will not be transfered!" msgstr "" -#: module/setup.py:407 +#: module/setup.py:392 msgid "Configpath" msgstr "" -#: module/setup.py:415 +#: module/setup.py:400 msgid "Configpath changed, setup will now close, please restart to go on." msgstr "" -#: module/setup.py:416 +#: module/setup.py:401 msgid "Press Enter to exit." msgstr "" -#: module/setup.py:420 +#: module/setup.py:405 #, python-format msgid "Setting config path failed: %s" msgstr "" -#: module/setup.py:425 +#: module/setup.py:411 #, python-format msgid "%s: OK" msgstr "" -#: module/setup.py:427 +#: module/setup.py:413 #, python-format msgid "%s: missing" msgstr "" #: module/setup.py:456 -msgid "[y]/n" +msgid "" +"Warning: Consider a password of 10 or more symbols if you expect to access " +"from outside your local network (ex. internet)." msgstr "" -#: module/setup.py:458 -msgid "y/[n]" +#: module/setup.py:457 +msgid "Password: " msgstr "" -#: module/setup.py:470 -msgid "Password: " +#: module/setup.py:461 +#, python-format +msgid "Password too short! Use at least %s symbols." msgstr "" -#: module/setup.py:475 -msgid "Password to short. Use at least 4 symbols." +#: module/setup.py:464 +msgid "Password must be alphanumeric." msgstr "" -#: module/setup.py:481 +#: module/setup.py:467 msgid "Password (again): " msgstr "" -#: module/setup.py:488 +#: module/setup.py:473 msgid "Passwords did not match." msgstr "" -#: module/setup.py:499 +#: module/setup.py:489 msgid "yes" msgstr "" -#: module/setup.py:499 +#: module/setup.py:489 msgid "true" msgstr "" -#: module/setup.py:499 +#: module/setup.py:489 msgid "t" msgstr "" -#: module/setup.py:502 +#: module/setup.py:492 msgid "no" msgstr "" -#: module/setup.py:502 +#: module/setup.py:492 msgid "false" msgstr "" -#: module/setup.py:502 +#: module/setup.py:492 msgid "f" msgstr "" -#: module/setup.py:505 module/setup.py:516 +#: module/setup.py:495 module/setup.py:505 msgid "Invalid Input" msgstr "" diff --git a/locale/si/LC_MESSAGES/django.po b/locale/si/LC_MESSAGES/django.po new file mode 100644 index 000000000..bc193cfa5 --- /dev/null +++ b/locale/si/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Sinhala\n" +"Language: si_LK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "නඞ" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "à¶Žà·âරධà·à¶±" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "à¶à¶žà¶±à·à¶±à·à¶à¶º" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "à¶
à·à¶œà¶à¶à· à¶à¶»à¶±à·à¶±" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/si/LC_MESSAGES/pyLoad.po b/locale/si/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..053e865c6 --- /dev/null +++ b/locale/si/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Sinhala\n" +"Language: si_LK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/si/LC_MESSAGES/pyLoadCli.po b/locale/si/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..f859072ff --- /dev/null +++ b/locale/si/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Sinhala\n" +"Language: si_LK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/si/LC_MESSAGES/setup.po b/locale/si/LC_MESSAGES/setup.po new file mode 100644 index 000000000..c9bbb5513 --- /dev/null +++ b/locale/si/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Sinhala\n" +"Language: si_LK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/sq/LC_MESSAGES/django.po b/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 000000000..cd2449a47 --- /dev/null +++ b/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Albanian\n" +"Language: sq_AL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/sq/LC_MESSAGES/pyLoad.po b/locale/sq/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..1f6ed52b9 --- /dev/null +++ b/locale/sq/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Albanian\n" +"Language: sq_AL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/sq/LC_MESSAGES/pyLoadCli.po b/locale/sq/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..73f7e3230 --- /dev/null +++ b/locale/sq/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Albanian\n" +"Language: sq_AL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/sq/LC_MESSAGES/setup.po b/locale/sq/LC_MESSAGES/setup.po new file mode 100644 index 000000000..0e0e1d124 --- /dev/null +++ b/locale/sq/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Albanian\n" +"Language: sq_AL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/sr/LC_MESSAGES/django.mo b/locale/sr/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index 2f03721f1..000000000 --- a/locale/sr/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/sr/LC_MESSAGES/django.po b/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 000000000..f298d0667 --- /dev/null +++ b/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Serbian (Cyrillic)\n" +"Language: sr_SP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "ÐПвО заÑ
Ñев за пÑПвеÑÑ" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "ÐПлОЌП Ўа пÑПÑОÑаÑе ÑекÑÑ Ñа пÑПвеÑе." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad ÑеÑÑаÑÑПваМ" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "ОÑкÑÑÑеМП" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "УÑпеÑМП ПбавÑеМП" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "ÑкÑÑÑеМП" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Ðа лО ÑÑе ÑОгÑÑМО Ўа желОÑе Ўа ОÑкÑÑÑОÑе pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "РеÑÑаÑÑПваÑО везÑ" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "ÐбÑОÑаÑО везÑ" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "УМеÑОÑе ОЌе пакеÑа." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "ÐлОкМОÑе Ма ЎеÑÐœÑ ÑÑÑÐ°ÐœÑ Ð¿ÑПвеÑе." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "ÐеÑОла Ñе гÑеÑка." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "ЀаÑÑОкла Ñе пÑазМа" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "ÐеÑÑпелП" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "ÐеЌа заÑ
Ñева за пÑПвеÑÑ" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "ÐПзОМке Ñе Ме пПклапаÑÑ" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "ÐПЎеÑаваÑа ÑаÑÑваМа." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "ÐПва ÑаÑÑОкла" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Ðа лО ÑÑе ÑОгÑÑМО Ўа желОÑе Ўа ÑеÑÑаÑÑÑеÑе pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "ÑекаЌ %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "ÐкÑОвМа пÑеÑзОЌаÑа" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "ÐÑÑа" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "ÐÑеÑзОЌаÑа" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "ÐзвеÑÑаÑО" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "ÐПЎеÑаваÑе" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "ÐЌе" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "СÑаÑÑÑ" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "ÐМÑПÑЌаÑОÑа" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "ÐелОÑОМа" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "ÐапÑеЎак" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "ÐÑОÑава" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "ÐПÑОÑМОÑкП ОЌе" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "ÐПзОМка" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "ÐЌе О лПзОМка Ме ПЎгПваÑаÑÑ. ÐПМПвОÑО." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Ðа бО ÑеÑеÑПвалО пПЎаÑке пÑОÑаве ОлО за ЎПЎаваÑе кПÑОÑМОка:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "ÐбÑОÑО завÑÑеМП" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "РеÑÑаÑÑПваÑе МеÑÑпеÑМП" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "ЀаÑÑОкла:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "ÐПзОМка:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "УÑеЎО пакеÑ" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "УÑеЎО ЎеÑаÑе пÑкеÑа." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "ÐЌе пакеÑа." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "ЀаÑÑОкла" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "ÐЌе пПЎÑаÑÑОкле за Пва пÑеÑзОЌаÑа." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "СпОÑак лПзОМке за Ð ÐÐ ." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "СаÑÑваÑ" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "РеÑеÑ" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "УÑпеÑМП ÑÑе Ñе ПЎÑавОлО." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "ÐÑÑаÑа" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "абÑПлÑÑМП" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "ÑелаÑОвМП" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "ОЌе" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "велОÑОМа" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "ÑОп" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "заЎÑа пÑПЌеМа" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "ÑПЎОÑеÑÑка ÑаÑÑОкла" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "МеЌа ÑаЎÑжаÑа" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "ÐпÑÑе" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "ÐПЎаÑÑО" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "ÐалПзО" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "ÐЎабÑаÑО ÑекÑОÑÑ ÐžÐ· ЌеМОÑа" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "ÐÑОкÑÑÑак" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "ÐÑеЌОÑÑÐŒ" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "ÐажО ЎП" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "ÐÑеПÑÑалО пÑПÑПк" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "ÐÑеЌе" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "ÐÐ°ÐºÑ ÐžÑÑПвÑеЌеМП" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "ÐбÑОÑО?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "ОÑпÑавМП" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "МОÑе важМП" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "Ўа" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "Ме" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "ÐПЎаÑ" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "ÐÐŸÐŽÐ°Ñ ÐœÐ°Ð»ÐŸÐ³" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Ð£ÐœÐŸÑ Ð¿ÐŸÐŽÐ°Ñака за ÑпПÑÑÐµÐ±Ñ Ð¿ÑеЌОÑÑÐŒ ЌПгÑÑМПÑÑО." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "ÐаÑе ОЌе:" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "ÐПзОМка за ÐŸÐ²Ð°Ñ ÐœÐ°Ð»ÐŸÐ³" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "ТОп" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "ÐЎабÑаÑО Ñ
ПÑÑ ÐаÑег МалПга." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "СÑаÑÑÑÑ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "МазаЎ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "ЎаÑе" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "ÐÑаÑ" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "ÐеÑÑО" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "ÐПЎÑÑка" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "СОÑÑеЌ" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "ÐС:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "ÐеÑзОÑа pyLoad-а:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "ЀаÑÑОкла ОМÑÑалаÑОÑе:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "ЀаÑÑОкла пПЎеÑаваÑа:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "ЀаÑÑОкла пÑеÑзОЌаÑа:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "ÐÑПÑÑПÑ:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "ÐезОк:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "ÐПÑÑ Ð²ÐµÐ±ÐžÐœÑеÑÑеÑÑа:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "ÐПÑÑ ÑЎаÑеМПг ОМÑеÑÑеÑÑа:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "ÐПЎеÑаваÑе" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "ÐеМаÑÐµÑ ÐŽÐ°ÑПÑеке" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "ÐÐŸÐŽÐ°Ñ Ð¿Ð°ÐºÐµÑ" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "ÐÑОлепО лОМкПве ОлО пПÑлаÑО кПМÑеÑМеÑ." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "ÐЌе МПвПг пакеÑа." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Ðезе" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "ÐÑОлепОÑе везе ОлО ÑекÑÑ Ðž ÑÑОÑМОÑе ÐŽÑгЌе ЀОлÑеÑ." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "ЀОлÑÑОÑÐ°Ñ Ð£Ð Ð" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "ÐПзОМка за Ð ÐРаÑÑ
Ове" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "ÐаÑПÑека" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "ÐПÑаÑО кПМÑеÑМеÑ." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "ÐÐŽÑеЎОÑÑе" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "ЧОÑаÑе пÑПвеÑе" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "ÐÑПвеÑа" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "ÐÑПвеÑа." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "ТекÑÑ" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "УМеÑО ÑекÑÑ ÐžÐ· пÑПвеÑе." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "ÐаÑвПÑО" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "ÐебОМÑеÑÑеÑÑ" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "ÐжÑÑОÑаÑа ÑÑ ÐŽÐŸÑÑÑпМа!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "ÐПЎаÑÑО ÑÑ Ð°Ð¶ÑÑОÑаМО, ÑеÑÑаÑÑПваÑО!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "ЧекаÑе пÑПвеÑе" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "ÐÐŽÑава" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "ÐЎЌОМОÑÑÑÑÑ" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "ÐМÑП" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "ÐПгÑÑÑе Ñе!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "ÐаÑÑÑавО" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "ÐÑкажО" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "ÐÑеÑзЌО:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "ÐПМПвМа веза:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "ÐÑзОМа:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "ÐкÑОвМП:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "ÐПМПвП ÑÑОÑÐ°Ñ ÑÑÑаМÑ" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "ÑÑОÑаваÑе" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "ÐазаЎ Ма вÑÑ
" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "ÐÑкÑÑÑОÑО pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "РеÑÑаÑÑПваÑО pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Ðа ЎПЎаваÑе/пÑПЌеМе Ð»ÐŸÐ·ÐžÐœÐºÑ ÑпПÑÑебОÑО:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "ÐажМП! ÐЎЌОМ кПÑОÑМОк Ñвек ОЌа Ñва пÑава!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "ÐÑПЌеМО лПзОМкÑ" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "ÐЎЌОМОÑÑÑаÑПÑ" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "ÐПзвПле" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "пÑПЌеМО" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "УМеÑО ÑÑеМÑÑÐœÑ Ðž жеÑÐµÐœÑ Ð»ÐŸÐ·ÐžÐœÐºÑ." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "ÐПÑОÑМОк" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "ТÑеМÑÑМа лПзОМка" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "ÐПва лПзОМка" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "ÐПва лПзОМка:" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "ÐПва лПзОМка (пПМПвО)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "ÐПМПвОÑО ÐœÐŸÐ²Ñ Ð»ÐŸÐ·ÐžÐœÐºÑ." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "ÐеЌаÑе пÑавП за пÑОÑÑÑп ÐŸÐ²ÐŸÑ ÑÑÑаМО." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "ЀаÑÑОкла пÑеÑзОЌаÑа МОÑе МаÑеМа." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "МеПгÑаМОÑеМП" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "МОÑе ЎПÑÑÑпМП" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÐПкÑеМÑÑО pyload.py -s за пÑОÑÑÑп пПЎеÑаваÑÑ." + diff --git a/locale/sr/LC_MESSAGES/pyLoad.mo b/locale/sr/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index e66d60ec6..000000000 --- a/locale/sr/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/sr/LC_MESSAGES/pyLoad.po b/locale/sr/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..44cad0c91 --- /dev/null +++ b/locale/sr/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Serbian (Cyrillic)\n" +"Language: sr_SP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "ÐÑОЌÑеМ Ñе ÑОгМал за Озлазак" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad Ð²ÐµÑ ÑаЎО Ñа бÑПÑеЌ %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° пÑПЌеМОЌ гÑÑпÑ: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° пÑПЌеМОЌ кПÑОÑМОка: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "ÑаÑÑОкла за ОзвеÑÑаÑе" + +#: module/Core.py:340 +msgid "Starting" +msgstr "ÐПкÑеÑеЌ" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "ÐÑМПвМа ÑаÑÑОкла: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pycrypto за ЎеÑОÑÑПваÑе кПМÑеÑМеÑа" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "ÑаÑÑОкла за пÑОвÑеЌеМе ЎаÑПÑеке" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "ÑаÑÑОкла за пÑеÑзОЌаÑа" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL за ÑОгÑÑМПÑМе везе" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "ÐÑеЌеÑÑаÑе ÑÑаÑОÑ
пПЎеÑаваÑа Ñ Ð±Ð°Ð·Ñ" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "ÐÑПвеÑОÑе ваÑе пПЎаÑке пÑОÑавÑОваÑа Ñа ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Све везе ÑÑ ÑклПÑеМе" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "ÐÑеЌе пÑеÑзОЌаÑа: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "СлПбПЎМП пÑПÑÑПÑа: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "ÐкÑОвОÑаЌ МалПгеâŠ" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "ÐкÑОваÑОÑа ЎПЎаÑка..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad Ñе ÑпÑеЌаМ за кПÑОÑÑеÑе" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "пПМПвМП пПкÑеÑаÑе pyLoad-а" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad Ñе заÑваÑа" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "ÐМÑÑалаÑОÑа %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "Ме ÐŒÐŸÐ³Ñ ÐŽÐ° МаÑеЌ %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "Ме ÐŒÐŸÐ³Ñ ÐŽÐ° кÑеОÑаЌ %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "ОÑкÑÑÑÑÑеЌâŠ" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "гÑеÑка пÑО ОÑкÑÑÑОваÑÑ" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "ÑбОÑО pyLoad Оз ÑеÑЌОМала" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "Ðаза Ñе ОзбÑОÑаМП збПг МекПЌпаÑОбОлМе веÑзОÑе." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Ðаза Ме ЌПже Ўа Ñе кПМвеÑÑÑÑе" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Ðаза Ñе кПМвеÑÑПваМа Ñа v2 Ñ v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Ðаза Ñе кПМвеÑÑПваМа Ñа v3 Ñ v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "ÐПМвеÑÑПваÑе ÑÑаÑе Django базе" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "завÑÑеМП" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "ваМ ÐŒÑеже" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "Ма ÐŒÑежО" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "Ма ÑекаÑÑ" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "пÑеÑкПÑеМП" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "ÑекаЌ" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "пÑОвÑеЌеМП ваМ ÐŒÑеже" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "запПÑОÑеЌ" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "МеÑÑпелП" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "пÑекОМÑÑП" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "ЎеÑОÑÑÑÑеЌ" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "пÑОлагПÑеМП" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "пÑеÑзОЌаЌ" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "ПбÑаÑÑÑеЌ" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "МепПзМаÑП" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "ÐÐ°ÐºÐµÑ Ñе завÑÑеМ: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "УпПÑÑеба SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "ÐÑеÑка ÑЎаÑеМПг ÑОЎа: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "ÐПкÑеÑеЌ %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° ÑÑОÑаЌ пПзаЎОМÑÐºÑ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÑ %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "ÑекаЌ %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL ÑеÑÑОÑОкаÑО МОÑÑ Ð¿ÑПМаÑеМО." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "ÐЎпÑÑÑОлО ÑЌП пПЎÑÑÐºÑ ÐŽÐ° бО ÑÑаÑÑПвалО %s ЎОÑекÑМП Ñа pyLoad" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "ÐПжеÑе Ўа ÑпПÑÑебОÑе ÑеÑÐ²ÐµÑ Ñа МавПÑПЌ кПÑО пÑÑжа ЎПбÑе пеÑÑПÑЌаМÑе О ÑÑл," + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "а ЌПжеÑе О Ўа МаÑÑавОÑе Ñа ваÑОЌ %s Ñа pyLoads fastcgi ÑеÑвеÑПЌ" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "пÑОЌеÑе пПЎеÑаваÑа ÑÑ Ñ ÑаÑÑОклО module/webui/servers" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° ÑпПÑÑебОЌ %(server)s, python-flup МОÑе ОМÑÑалОÑаМ!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "ÐÑеÑка ÑвПза lightweight ÑеÑвеÑа: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "ТÑебаÑе Ўа пÑеÑзЌеÑе О кПЌпОлÑÑеÑе bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "ÐПпОÑаÑÑе boern.so Ñ ÑаÑÑÐžÐºÐ»Ñ module/lib ОлО ÑпПÑÑебОÑе setup.py install" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "ÐаÑавМП ÑÑебаÑе Ўа пПзМаÑеÑе лОМÑÐºÑ Ðž Ўа зМаÑе какП Ўа кПМпОлÑÑеÑе пÑПгÑаЌе" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "СеÑÐ²ÐµÑ Ð¿ÐŸÑÑавÑеМ Ма МавПÑеМ, збПг пÑПблеЌа Ма ÐОМЎПз." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "ÐÐ²Ð°Ñ ÑеÑÐ²ÐµÑ ÐœÐµ пПЎÑжава SSL. УЌеÑÑП Ñега кПÑОÑÑОÑе ÑгМежЎеМО." + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "СÑаÑÑПваÑе ÑгÑаÑеМПг ÑеÑвеÑа: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "СÑаÑÑПваÑе МавПÑеМПг ССРвеб ÑеÑвеÑа: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "СÑаÑÑПваÑе МавПÑеМПг веб ÑеÑвеÑа: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "СÑаÑÑПваÑе fastcgi ÑеÑвеÑа: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "СÑаÑÑПваÑе вебÑеÑвеÑа (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "ÐеЌаÑе пÑавП за пÑОÑÑÑп ÐŸÐ²ÐŸÑ ÑÑÑаМО." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "ЀаÑÑОкла пÑеÑзОЌаÑа МОÑе МаÑеМа." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "МеПгÑаМОÑеМП" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "МОÑе ЎПÑÑÑпМП" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "ÐПкÑеМÑÑО pyload.py -s за пÑОÑÑÑп пПЎеÑаваÑÑ." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "ÐЎлПЌÑО пÑеÑзОЌаÑа МОÑÑ ÑÑпелО. ÐÑаÑаÑе Ма ÑÐµÐŽÐœÑ Ð²ÐµÐ·Ñ | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "ÐÑеÑзОЌаÑе Ñе запПÑеÑП: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "ÐÑеÑзОЌаÑе Ñе завÑÑеМП: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "ÐÑОкÑÑÑÐºÑ %s МеЎПÑÑаÑе ÑÑМкÑОÑа." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "ÐÑеÑзОЌаÑе Ñе пÑекОМÑÑП: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "ÐÑеÑзОЌаÑе Ñе пПМПвП пПкÑеМÑÑП: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "ÐÑеÑзОЌаÑе Ñе ваМ ÐŒÑеже: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "ÐÑеÑзОЌаÑе Ñе ÑÑеМÑÑМП ваМ ÐŒÑеже: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "ÐÑеÑзОЌаÑе МОÑе ÑÑпелП: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° Ñе пПвежеЌ Ñа Ñ
ПÑÑПЌ ОлО Ñе веза пÑекОМÑÑа. ÐПМПвМП пПвезОваÑе за 1 ЌОМÑÑ." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "ÐÑеÑзОЌаÑе Ñе пÑеÑкПÑеМП: %(name)s збПг %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "ÐеÑОÑÑПваÑе пПÑелП: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "ÐеÑÑпеÑМП ЎеÑОÑÑПваÑе: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "ÐПМавÑаÑе %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° пÑеÑзЌеЌ пПЎаÑке за %(name)s | %(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "ÐÑеÑка пПкÑеÑаÑа кÑке: %s" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° акÑОвОÑаЌ %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "ÐкÑÐžÐ²ÐœÑ ÐŽÐŸÐŽÐ°ÑÑО: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "ÐеакÑОвМО ЎПЎаÑÑО: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "ÐеÑÑпеÑМП пПМПвМП пПвезОваÑе: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "СкÑÐžÐ¿Ñ Ð·Ð° пПМПвМП пПвезОваÑе МОÑе пÑПМаÑеМ." + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "ÐПкÑеÑеЌ пПМПвМП пПвезОваÑе" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° ОзвÑÑОЌ ÑкÑÐžÐ¿Ñ Ð·Ð° пПМПвМП пПвезОваÑе." + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "ÐПМПвП Ñе пПвезаМП; МПва IP аЎÑеÑа: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "ÐеЌа ЎПвПÑМП пÑПÑÑПÑа Ма ÑÑеÑаÑÑ" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° Ñе пÑОÑавОЌ Ñа МалПгПЌ %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "ÐеОÑпÑавМа лПзОМка" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "ÐÑеЌе %s ОЌа Ð»ÐŸÑ ÑПÑЌаÑ, ÑпПÑÑебО: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "ÐалПг %s МеЌа ЎПвПÑМП ÑаПбÑаÑаÑа. ÐÑПвеÑаваЌ пПМПвП за 30 ЌОМÑÑа." + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "ÐалПг %s Ñе ОÑÑекаП. ÐÑПвеÑаваЌ пПМПвП за ÑÐ°Ñ Ð²ÑеЌеМа." + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "ÐПÑÑОгМÑÑП Ñе ПгÑаМОÑеÑе пÑеÑзОЌаÑа" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s ОЌа МеважеÑО ПбÑазаÑ." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "ÐÑеÑка ÑвПза %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "ÐОÑеЎаМ Ñ
ПÑÑÐµÑ ÐœÐžÑе ÑÑОÑаМ" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "ÐкÑОвОÑаÑÑе ЎОÑекÑМП пÑеÑзОЌаÑе Ñ ÐœÐ°Ð»ÐŸÐ³Ñ Bitshare-а" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "LinkList Ме ЌПже Ўа бÑЎе ПбÑОÑаМ." + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "ÐПЎеÑаваÑа МалПга ОзбÑОÑаМе збПг МПвОÑег ÑПÑЌаÑа." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "ÐПÑÑебМа Ñе пÑПвеÑа ОЎеМÑОÑеÑа (кПÑОÑМОÑкП ОЌе О лПзОМка)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "УМеÑОÑе МалПг Ма ÑеÑвОÑÑ %s ОлО ЎеакÑОвОÑаÑÑе ÐŸÐ²Ð°Ñ Ð¿ÑОкÑÑÑак." + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "ÐÑПМаÑеМ Ñе HTML кÎЎ Ñ Ð¿ÑеÑзеÑÐŸÑ ÐŽÐ°ÑПÑеÑО (%s). ÐÑеÑзОЌаÑе Ñе пПМПвП бОÑО пПкÑеМÑÑП." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "ÐаÑПÑека ÑÑеМÑÑМП МОÑе ЎПÑÑÑпМа" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: ÑекаÑе ОзЌеÑÑ Ð¿ÑеÑзОЌаÑа %d Ñ." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: ÑекаÑе пПÑвÑЎМПг кПЎа %d Ñ." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "ÐÑеÑзеÑа ЎаÑПÑека Ñе пÑазМа" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "API кÑÑÑ Ñе МеОÑпÑаваМ" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: МеЌаÑе ЎПвПÑМП ÑаПбÑаÑаÑа" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "ÐÑекПÑаÑОлО ÑÑе ÑаПбÑаÑаÑ" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: ЎеÑеÑе ÑаПбÑаÑаÑа (ЎОÑекÑМП пÑеÑзОЌаÑе)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "ÐÐµÑ Ð¿ÑеÑзОЌаÑе Ñа Пве IP аЎÑеÑе. СаÑекаÑÑе 60 ÑекÑМЎО." + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "ÐеОÑпÑаваМ кÎЎ за пÑПвеÑÑ ÐžÐŽÐµÐœÑОÑеÑа. ÐÑеÑзОЌаÑе Ñе пПМПвП бОÑО пПкÑеМÑÑП." + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "Rapidshare.com: МеЌа ÑлПбПЎМОÑ
ÑлПÑПва" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "ÐПÑÑебаМ ваЌ Ñе пÑеЌОÑÑÐŒ МалПг Ўа бОÑÑе пÑеÑзелО ÐŸÐ²Ñ ÐŽÐ°ÑПÑекÑ" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "ÐÑОÑавÑеМП ОЌе ЎаÑПÑеке МОÑе ОÑпÑавМП" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "ÐÑеÑка Ñ ÐžÑÑПвÑеЌеМПЌ пÑеÑзОЌаÑÑ. СаÑекаÑÑе 60 ÑекÑМЎО." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "ÐОÑÑе пÑОÑавÑеМО." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "ÐеÑОÑÑПваÑе МОÑе ÑÑпелП" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "У URL аЎÑеÑО МОÑе МавеЎеМ кÑÑÑ ÐŽÐ°ÑПÑеке" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "ÐÃŽÐŽ гÑеÑке:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "ÐаÑПÑека Ме пПÑÑПÑО." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** ÐÑОкÑÑÑÑО ÑÑ Ð°Ð¶ÑÑОÑаМО. ÐПМПвП пПкÑеМОÑе pyLoad. ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "ÐÑОкÑÑÑÑО ÑÑ Ð°Ð¶ÑÑОÑаМО О пПМПвП ÑÑОÑаМО" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "ÐеЌа ажÑÑОÑаÑа пÑОкÑÑÑака" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "ÐеЌа МПве веÑзОÑе pyLoad-а" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** ÐПÑÑÑпМа Ñе МПва веÑзОÑа, pyLoad %s ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** ÐÑеÑзЌОÑе Ñе ПЎавЎе: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° Ñе пПвежеЌ Ñа ÑеÑвеÑПЌ за ажÑÑОÑаÑа" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "ÐПва веÑзОÑа %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "ÐÑеÑка пÑО ажÑÑОÑаÑÑ %s" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "ÐеÑзОÑе Ñе Ме пПклапаÑÑ" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "ÐÑеÑзОЌаÑе Ñе завÑÑеМП: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "ÐПвО заÑ
Ñев пПÑвÑЎМПг кПЎа: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "ÐЎгПвПÑОÑе Ñа âc %s ÑекÑÑ ÐœÐ° пПÑвÑЎМПЌ кПЎÑâ" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "ÐПЎаÑП %s Оз HotFolder-а" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "ÐОÑе ОМÑÑалОÑаМ %s" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° акÑОвОÑаЌ %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "ÐкÑОвОÑаМП" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "ÐОÑÑ Ð°ÐºÑОвОÑаМО пÑОкÑÑÑÑО за ÑаÑпакОваÑе" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "ÐÐ°ÐºÐµÑ %s Ñе ÑÑавÑеМ Ñ ÑеЎ за ÑаÑпакОваÑе" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "ÐÑПвеÑО Ð¿Ð°ÐºÐµÑ %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "РаÑпакÑÑ Ñ %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "ÐеЌа ЎаÑПÑека за ÑаÑпакОваÑе" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "ÑаÑпакÑÑеЌ" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "ÐаÑÑОÑеМП лПзОМкПЌ" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "ÐеОÑпÑавМа лПзОМка" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "ÐÑОÑеЌ %s ЎаÑПÑека" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "РаÑпакОваÑе Ñе завÑÑеМП" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "ÐÑеÑка Ñ Ð°ÑÑ
ОвО" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC Ñе Ме пПклапа" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "ÐепПзМаÑа гÑеÑка" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "ÐПÑÑавÑаÑе кПÑОÑМОка О гÑÑпе МОÑе ÑÑпелП" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: пПÑÑ 9666 Ð²ÐµÑ Ñе Ñ ÑпПÑÑебО" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "ÐÑеПÑÑалП Ñе %s кÑеЎОÑа" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° пПÑаÑеЌ ПЎгПвПÑ." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "У ваÑеЌ ÐœÐ°Ð»ÐŸÐ³Ñ ÐœÐ° ÑеÑвОÑÑ CaptchaTrader МеЌа ЎПвПÑМП кÑеЎОÑа." + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "СпОÑак ÑОÑÑаÑПÑа МОÑе пÑПМаÑеМ" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "СпОÑак ÑОÑÑаÑПÑа Ñе пÑазаМ" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "ÐÑеÑзОЌаÑе Ñе завÑÑеМП: %(name)s @ %(plugin)s" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "ÐПвО CaptchaID ПЎ ПÑпÑеЌаÑа: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "У ваÑеЌ ÐœÐ°Ð»ÐŸÐ³Ñ ÐœÐ° ÑеÑвОÑÑ 9kw.eu МеЌа ЎПвПÑМП кÑеЎОÑа." + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "ÐМÑÑалОÑаМО ÑкÑОпÑО за %s: " + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "СкÑОпÑа Ме ЌПже Ўа Ñе ОзвÑÑО:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "ÐÑеÑка Ñ %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "У ваÑеЌ ÐœÐ°Ð»ÐŸÐ³Ñ ÐœÐ° ÑеÑвОÑÑ ExpertDecoders МеЌа ЎПвПÑМП кÑеЎОÑа." + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "ÐÑвП ЎПЎаÑÑе МалПг Ма ÑеÑвОÑÑ rehost.to па пПМПвП пПкÑеМОÑе pyLoad." + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "ÐÑеПÑÑалП Ñе %d кÑеЎОÑа" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Pil О Tesseract МОÑÑ ÐžÐœÑÑалОÑаМО, МОÑО Ñе пПвезаМ клОÑÐµÐœÑ ÑаЎО ЎеÑОÑÑПваÑа пПÑвÑЎМОÑ
кПЎПва." + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "ÐО ÑеЎаМ ÑезÑлÑÐ°Ñ Ð¿ÑПвеÑе МОÑе пÑОЌÑеМ Ñ Ð²ÑÐµÐŒÐµÐœÑ ÐŸÐŽ бОлП кПÑег ЎПЎаÑка." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "ÐПÑÑавÑаÑе кПÑОÑМОка О гÑÑпе МОÑе ÑÑпелП: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "ÐеЌа пÑОкаÑеМПг клОÑеМÑа за ЎеÑОÑÑПваÑе пÑПвеÑе" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "ÐÐŸÐŽÐ°Ñ Ð¿Ð°ÐºÐµÑ %(name)s Ñа %(count)d везе(а)" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "ÐПЎаÑП %(count)d везе Ñ Ð¿Ð°ÐºÐµÑ #%(package)d" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "ÐОÑаЌ МаÑаП js ЌПÑПÑ, ОМÑÑалОÑаÑО Spidermonkey, ossp-js, pyv8 ОлО rhino" + diff --git a/locale/sr/LC_MESSAGES/pyLoadCli.mo b/locale/sr/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 6d4d21e9d..000000000 --- a/locale/sr/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/sr/LC_MESSAGES/pyLoadCli.po b/locale/sr/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..3cda02c25 --- /dev/null +++ b/locale/sr/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Serbian (Cyrillic)\n" +"Language: sr_SP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " ÐМÑеÑÑеÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÐœÐµ лОМОÑе" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s пÑеÑзОЌаÑа:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " ÐÑзОМа: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " ÐелОÑОМа: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " ÐавÑÑеМП: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr " ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "Ма ÑекаÑÑ: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "СÑаÑÑÑ:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "паÑзОÑаМП" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "пПкÑеМÑÑП" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "УкÑпМа бÑзОМа" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "ÐаÑПÑеке Ñ ÑпОÑкÑ" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "УкÑпМП" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "ÐеМО:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " ÐÐŸÐŽÐ°Ñ Ð²ÐµÐ·Ðµ" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " УпÑавÑÐ°Ñ ÑпОÑкПЌ" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " УпÑавÑÐ°Ñ ÑакÑпÑаÑеЌ" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr " ÐаÑзОÑаÑ/МаÑÑавО ÑеÑвеÑ" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " ÐкПМÑÐ°Ñ ÑеÑвеÑ" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " ÐзаÑО" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "ÐПÑОÑÑОÑе ÐŸÐ²Ñ ÑОМÑакÑÑ: add <ОЌе пакеÑа> <веза> <ÐŽÑÑга веза>âŠ" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "ÐÑПвеÑа %d веза:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "ÐаÑПÑека Ме пПÑÑПÑО." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad Ñе ПбÑÑÑавÑеМ" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "КÑаЌпа ÑÑаÑÑÑ ÑеÑвеÑа" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "КÑаЌпа пÑеÑзОЌаÑа Ñ ÑпОÑкÑ" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "КÑаЌпа пÑеÑзОЌаÑа Ñ ÑакÑпÑаÑÑ" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "ÐПЎаÑе Ð¿Ð°ÐºÐµÑ Ñ ÑпОÑак" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "ÐПЎаÑе Ð¿Ð°ÐºÐµÑ Ñ ÑакÑпÑаÑ" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "ÐÑОÑе ЎаÑПÑеке Оз ÑпОÑка/ÑакÑпÑаÑа" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "ÐÑОÑе пакеÑе Оз ÑпОÑка/ÑакÑпÑаÑа" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "ÐÑеЌеÑÑа пакеÑе Оз ÑпОÑка Ñ ÑакÑпÑÐ°Ñ Ðž ПбÑМÑÑП" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "ÐПМПвП пПкÑеМО ЎаÑПÑеке" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "ÐПМПвП пПкÑеМО пакеÑе" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "ÐÑПвеÑава ЎПÑÑÑпМПÑÑ (ÑаЎО Ñа лПкалМОЌ кПМÑеÑМеÑПЌ)" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "ÐÑПвеÑава ЎПÑÑÑпМПÑÑ ÐŽÐ°ÑПÑеке кПМÑеÑМеÑа" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "ÐаÑзОÑÐ°Ñ ÑеÑвеÑ" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "МаÑÑавО пÑеÑзОЌаÑа" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "ÐаÑзОÑаÑ/МаÑÑавО" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "ПкПМÑÐ°Ñ ÑеÑвеÑ" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "СпОÑак кПЌаМЎО:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° пОÑеЌ Ма ЎаÑПÑÐµÐºÑ Ñа пПЎеÑаваÑОЌа" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "ТÑеба ваЌ py-openssl Ўа бО Ñе пÑОвезалО Ма pyLoad ÑезгÑП." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "ÐÐŽÑеÑа: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "ÐПÑÑ: " + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "ÐПÑОÑМОÑкП ОЌе: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "ÐПзОМка: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "ÐПЎаÑО за пÑОÑÐ°Ð²Ñ ÑÑ Ð¿ÐŸÐ³ÑеÑМО." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° ÑÑпПÑÑавОЌ Ð²ÐµÐ·Ñ Ñа аЎÑеÑПЌ %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "ÐПÑÑебаМ ваЌ Ñе py-openssl Ўа бОÑÑе Ñе пПвезалО Ма ÑеÑÐ²ÐµÑ pyLoad-а." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "ÐаМеЌаÑеМ Ñе ОМÑеÑакÑОвМО ÑежОЌ ÑÐµÑ ÑÑе заЎалО Меке кПЌаМЎе." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "ÐПЎаÑÑе пакеÑ:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "УМеÑОÑе ОЌе МПвПг пакеÑа" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "ÐакеÑ: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "РаÑÑлаМОÑе везе кПÑе желОÑе Ўа ЎПЎаÑе." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "УМеÑОÑе %s каЎа завÑÑОÑе." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "ÐПЎаÑП веза: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " МазаЎ Ма главМО ЌеМО" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "УпÑавÑаÑÑе пакеÑОЌа:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "УпÑавÑаÑÑе везаЌа:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "КÑа желОÑе Ўа пÑеЌеÑÑОÑе?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "КÑа желОÑе Ўа ПбÑОÑеÑе?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "КÑа желОÑе Ўа пПМПвП пПкÑеМеÑе?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "ÐЎабÑаÑО ÑÑа Ўа Ñе ÑÑаЎО ОлО ÑМеÑО бÑÐŸÑ Ð¿Ð°ÐºÐµÑа." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "ПбÑОÑО" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "пÑеЌеÑÑО" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "пПМПвП пПкÑеМО" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " â пÑеÑÑ
ПЎМП" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " â ÑлеЎеÑе" + diff --git a/locale/sr/LC_MESSAGES/pyLoadGui.mo b/locale/sr/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 5ece99c01..000000000 --- a/locale/sr/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/sr/LC_MESSAGES/setup.mo b/locale/sr/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index 3ce6ecf6c..000000000 --- a/locale/sr/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/sr/LC_MESSAGES/setup.po b/locale/sr/LC_MESSAGES/setup.po new file mode 100644 index 000000000..710c3f54c --- /dev/null +++ b/locale/sr/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Serbian (Cyrillic)\n" +"Language: sr_SP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "ÐŽ" + +#: module/setup.py:53 +msgid "n" +msgstr "М" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "ÐПбÑП ЎПÑлО кПЎ пПЌПÑМОка за пПЎеÑаваÑе pyLoad-а." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "ÐМ Ñе пÑПвеÑОÑО ÑОÑÑеЌ О МаЌеÑÑОÑО ПÑМПвМе пПÑÑавке ÑакП Ўа ЌПжеÑе Ўа пПкÑеМеÑе pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "ÐÑеЎМПÑÑ Ñ ÑглаÑÑОЌ загÑаЎаЌа Ñе пПЎÑазÑЌеваМа." + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "акП Ме желОÑе Ўа пÑПЌеМОÑе ОлО МезМаÑе ÑÑа Ўа ОзабеÑеÑе, ÑÑОÑМОÑе 'еМÑеÑ'." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "ÐМаÑÑе: ЌПжеÑе пПМПвП Ўа пПкÑеМеÑе ÐŸÐ²Ð°Ñ Ð°ÑОÑÑÐµÐœÑ Ñа паÑаЌеÑÑПЌ --setup ОлО -s каЎа пПкÑÐµÐœÐµÑ pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "ÐкП ОЌаÑе пÑПблеЌа Ñа аÑОÑÑеМÑПЌ, ÑÑОÑМОÑе STRG-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "за пПМОÑÑаваÑе О МеЌПÑÑе Ўа га пПкÑеМеÑе аÑÑПЌаÑÑкО Ñа pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "ÐаЎа ÑÑе ÑпÑеЌМО Ўа пÑПвеÑОÑе ÑОÑÑеЌ, ÑÑОÑМОÑе 'еМÑеÑ'." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "ТÑеба ÐаЌ pycurl, sqlite О python 2.5, 2.6 ОлО 2.7 за пПкÑеÑаÑе pyLoad-а." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "ÐПпÑавОÑе ÑП О пПМПвП пПкÑеМОÑе pyLoad." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "СеÑап Ñе Ñе заÑвПÑОÑО." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "ÐÑПвеÑа ÑОÑÑеЌа Ñе завÑÑеМа, ÑÑОÑМОÑе 'еМÑеÑ' Ўа бО вОЎелО ÑезÑлÑаÑ." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## СÑаÑÑÑ ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "ЎеÑОÑÑПваÑе кПМÑеÑМеÑа" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "ÑÑл веза" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "аÑÑПЌаÑÑкП МалажеÑе пÑПвеÑе" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "ÐебОМÑеÑÑеÑÑ" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "МапÑеЎаМ Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "ÐПÑÑÑпМе ÑÑМкÑОÑе:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "ЀÑМкÑОÑе кПÑе МеЎПÑÑаÑÑ:" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "py-crypto МОÑе ЎПÑÑÑпаМ" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "ТП ÐаЌ ÑÑеба акП желОÑе Ўа ЎеÑОÑÑÑÑеÑе кПМÑеÑМеÑе." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "ССРМОÑе ЎПÑÑÑпаМ" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "ÐПÑÑебМП акП желОÑе Ўа ÑÑаЎОÑе ÑОгÑÑМПÑÐœÑ Ð²ÐµÐ·Ñ ÐœÐ° ÑезгÑП ОлО вебОМÑеÑÑеÑÑ." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "ÐкП желОÑе Ўа пÑОÑÑÑпОÑе pyLoad ÑаЌП лПкалМП, ССРМОÑе пПÑÑебМП." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "МОÑе ЎПÑÑÑпМП МалажеÑе пÑПвеÑе" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "ÐПÑÑебМП за Меке Ñ
ПÑÑеÑе О каП беÑплаÑаМ кПÑОÑМОк." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "Gui МОÑе ЎПÑÑÑпМП" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "ÐÑаÑОÑкО ОМÑеÑÑеÑÑ." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "МеЌа JavaScript ЌПÑПÑ" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "ТП ÐаЌ ÑÑеба за Меке Click'N'Load везе. ÐМÑÑалОÑаÑО Spidermonkey, ossp-js, pyv8 ОлО rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "ÐПжеÑе ÑаЎа Ўа заÑÑÑавОÑе О Ўа пПпÑавОÑе Меке завОÑМПÑÑО акП желОÑе." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "ÐаÑÑавОÑО Ñа пПЎеÑаваÑеЌ?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "ÐелОÑе лО Ўа пÑПЌеМОÑе пÑÑаÑÑ Ð·Ð° пПЎеÑаваÑе? ТÑеМÑÑМа пÑÑаÑа Ñе %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "ÐкП кПÑОÑÑОÑе pyLoad Ма ÑеÑвеÑÑ ÐžÐ»Ðž Ма паÑÑОÑОÑО Ма ОМÑеÑМПЌ ÑлеÑÑ, ЌПже Ўа бÑЎе ЎПбÑП Ўа пÑПЌеМОÑе." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "ÐÑПЌеМОÑО пÑÑаÑÑ Ð·Ð° пПЎеÑаваÑе?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "ÐелОÑе лО Ўа МаЌеÑÑОÑе пПЎаÑке за пÑОÑÐ°Ð²Ñ Ðž ПÑМПвМе пПÑÑавке?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "ÐвП Ñе пÑепПÑÑÑеМП Ма пÑвП пПкÑеÑаÑе." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "УÑаЎО ПÑМПÑМП пПЎеÑаваÑе?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "ÐелОÑе лО Ўа пПЎеÑОÑе SSL?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "ÐПЎеÑОÑО SSL?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Ðа Ñе кПМÑОгÑÑОÑе веб ОМÑеÑÑеÑÑ?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "ÐПЎеÑОÑО веб ОМÑеÑÑеÑÑ?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "ÐПЎеÑаваÑе Ñе ÑÑпеÑМП завÑÑеМП." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "ÐÑОÑОÑМОÑе Enter Ўа ОзаÑеÑе О пПМПвП пПкÑеМеÑе pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## ÐÑПвеÑа ÑОÑÑеЌа ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "ÐаÑа веÑзОÑа python Ñе ЌМПгП МПва, ÑпПÑÑебОÑе python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "ÐаÑа веÑзОÑа python Ñе пÑеÑÑаÑа, ÑпПÑÑебОÑе ÐŒÐ°ÐºÐ°Ñ python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "ÐеÑзОÑа Python: У ÑеЎÑ" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "ÐаÑа веÑзОÑа jinja2 %s ÐŽÐµÐ»Ñ Ð¿ÑеÑÑаÑа." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "ÐПжеÑе Ўа МаÑÑавОÑе, алО акП веб ОМÑеÑÑеÑÑ ÐœÐµ ÑаЎО," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "ажÑÑОÑаÑÑе ОлО ЎеОМÑÑалОÑаÑÑе га, pyLoad ОЌа ЎПвПÑМП jinja2 бОблОПÑекÑ." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "JS ЌПÑПÑ" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## ÐÑМПвМП пПЎеÑаваÑе ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "СлеЎеÑО пПЎаÑО за пÑОÑÐ°Ð²Ñ Ð²Ð°Ð¶Ðµ за CLI, GUI О веб ОМÑеÑÑеÑÑ." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "ÐПÑОÑМОÑкП ОЌе" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "ÐезОк" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "ЀаÑÑОкла пÑеÑзОЌаÑа" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "ÐакÑОЌалаМ бÑÐŸÑ ÐžÑÑПвÑеЌеМОÑ
пÑеÑзОЌаÑа" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "ÐПÑОÑÑОÑО пПМПвМП пПвезОваÑе?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "ÐПкаÑОÑа ÑкÑОпÑа за пПМПвМП пПвезОваÑе" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## ÐПЎеÑаваÑе веб ОМÑеÑÑеÑÑа ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "ÐкÑОвОÑаÑО веб ОМÑеÑÑеÑÑ?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "ÐÐŽÑеÑа за пÑОÑеЌ. ÐкП кПÑОÑÑОÑе 127.0.0.1 ОлО localhost, веб ОМÑеÑÑеÑÑ Ñе бОÑО ЎПÑÑÑпаМ ÑаЌП лПкалМП." + +#: module/setup.py:312 +msgid "Address" +msgstr "ÐÐŽÑеÑа" + +#: module/setup.py:313 +msgid "Port" +msgstr "ÐПÑÑ" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad пÑÑжа МекПлОкП ÑОÑÑеЌÑке пПЎÑÑке ÑеÑвеÑа, евП кÑаÑкП ПбÑаÑÑеÑе." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "ÐПЎÑазÑЌеваМ ÑеÑвеÑ, МаÑбПÑО ÐžÐ·Ð±ÐŸÑ Ð°ÐºÐŸ МезМаÑе кПÑО Ўа кПÑОÑÑОÑе." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "ÐÐ²Ð°Ñ ÑеÑÐ²ÐµÑ Ð¿ÑÑжа ССРО ЎПбÑа Ñе алÑеÑМаÑОва за ÑгÑаÑеМО." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "ÐПже Ўа га кПÑОÑÑО apache, lighttpd, пПÑÑебМП Ñе Ўа ОÑ
пПЎеÑОÑе, ÑÑП МОÑе МаÑлакÑе." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "ÐÑлП бÑза алÑеÑМаÑОва пОÑаМа Ñ ÐŠ, пПÑÑебМП libev/лОМÑÐºÑ Ð·ÐœÐ°Ñе." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "УзеÑО га ПвЎе: https://github.com/jonashaag/bjoern кПЌпОлÑÑÑе га" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "О кПпОÑаÑÑе bjoern.so Ñ module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "ÐажÑа: Ñ ÐœÐµÐºÐžÐŒ ÑлÑÑаÑевОЌа ÑгÑаÑеМ ÑеÑÐ²ÐµÑ ÐœÐµ ÑаЎО, акП ОЌаÑе пÑПблеЌа Ñа веб ОМÑеÑÑеÑÑПЌ" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "вÑаÑОÑе Ñе ПвЎе О пÑПЌеМОÑе ÑгÑаÑеМ ÑеÑÐ²ÐµÑ Ñа МавПÑеМОЌ." + +#: module/setup.py:329 +msgid "Server" +msgstr "СеÑвеÑ" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## ÐПЎеÑаваÑе SSL-а ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "ÐПкÑеМОÑе Пве кПЌаМЎе Оз pyLoad ÑаÑÑОкле пПЎеÑаваÑа Ўа бО ÑÑаЎОлО ССРÑеÑÑОÑОкаÑе:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "ÐкП ÑÑе завÑÑОлО ÐžÑ Ñве Ñе Ñ ÑеЎÑ, ЌПжеÑе ÑаЎа Ўа акÑОвОÑаÑе ССÐ." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "ÐкÑОвОÑаÑО SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "ÐзабеÑОÑе ÑаЎÑÑ" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 â кÑеОÑаÑÑе/ÑÑеЎОÑе кПÑОÑМОка" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 â ОзлОÑÑаÑÑе кПÑОÑМОке" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 â ÑклПМОÑе кПÑОÑМОка" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 â ОзаÑОÑе" + +#: module/setup.py:376 +msgid "Users" +msgstr "ÐПÑОÑМОÑО" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "ÐПЎеÑаваÑе МПве пÑÑаÑе, акÑÑелМа кПМÑОгÑÑаÑОÑа МеÑе бОÑО пÑеМеÑа!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "ÐÑÑаÑа кПМÑОгÑÑаÑОÑе" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "ÐÑÑаÑа пÑПЌеÑеМа, ÑеÑÐ°Ñ Ñе Ñе заÑвПÑОÑО, пПМПвП пПкÑеМОÑе за МаÑÑавак." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "ÐÑОÑОÑМОÑе Enter Ўа ОзаÑеÑе." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Ðе ÐŒÐŸÐ³Ñ ÐŽÐ° пПÑÑавОЌ пÑÑаÑÑ Ð·Ð° пПЎеÑаваÑе: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "%s: У ÑеЎÑ" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: ÑалО" + +#: module/setup.py:464 +msgid "Password: " +msgstr "ÐПзОМка: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "ÐПзОМка Ñе пÑекÑаÑка. УМеÑОÑе Ð±Ð°Ñ ÑеÑОÑО ÑОЌбПла." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "ÐПÑвÑЎа лПзОМке: " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "ÐПзОМке Ñе Ме пПклапаÑÑ" + +#: module/setup.py:493 +msgid "yes" +msgstr "Ўа" + +#: module/setup.py:493 +msgid "true" +msgstr "ÑаÑМП" + +#: module/setup.py:493 +msgid "t" +msgstr "Ñ" + +#: module/setup.py:496 +msgid "no" +msgstr "Ме" + +#: module/setup.py:496 +msgid "false" +msgstr "МеÑаÑМП" + +#: module/setup.py:496 +msgid "f" +msgstr "М" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "ÐеОÑпÑаваМ ÑМПÑ" + diff --git a/locale/sv/LC_MESSAGES/django.mo b/locale/sv/LC_MESSAGES/django.mo Binary files differdeleted file mode 100644 index c85b2c173..000000000 --- a/locale/sv/LC_MESSAGES/django.mo +++ /dev/null diff --git a/locale/sv/LC_MESSAGES/django.po b/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 000000000..b1c927a67 --- /dev/null +++ b/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Swedish\n" +"Language: sv_SE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Ny captchabegÀran" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "Var god lÀs texten pÃ¥ captchan." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad startades om" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "Ãr det sÀkert att du vill avsluta pyLoad?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "Starta om lÀnken" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "Radera lÀnken" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "Var god skriv in ett paketnamn." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "Var god kiicka pÃ¥ den rÀtta captchapositionen." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Ett fel intrÀffade." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Mappen Àr tom" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Inga captchor att lÀsa." + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Lösenorden stÀmde inte överens." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "InstÀllningar sparade." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Ny mapp" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "Ãr det sÀkert att du vill starta om pyLoad?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "vÀntar %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Aktiva hÀmtningar" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Hem" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "HÀmtningar" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Loggar" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Konfiguration" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "Förlopp" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Ditt anvÀndarnamn och lösenord stÀmde inte. Försök igen." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "För att Ã¥terstÀlla dina loginuppgifter eller lÀgga till en anvÀndare, kör:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Radera fÀrdiga" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "Omstart misslyckades" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Mapp:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Lösenord:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Redigera paket" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "Redigera paketdetaljerna hÀr." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Namnet pÃ¥ paketet." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Mappnamn för dessa nedladdningar." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Lösenordslista som anvÀnds vid uppackning." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Ã
terstÀll" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "Du har loggats ut." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "SökvÀg" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "absolut" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "relativ" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "namn" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "storlek" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "typ" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "senast Àndrad" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "förÀldrakatalog" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "inget innehÃ¥ll" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "TillÀggsprogram" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "VÀlj ett avsnitt frÃ¥n menyn" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Giltigt till" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Trafik kvar" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Tid" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Max samtidiga" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Ta bort?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "inte giltigt" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "ja" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "nej" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Skriv in dina kontouppgifter för att anvÀnda premiumfunktioner." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Ditt anvÀndarnamn." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Lösenord för detta konto." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "Starta" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "föreg" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "nÀsta" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Slut" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Nyheter" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad-version:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Installationsmapp:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Konfigurationsmapp:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "HÀmtningsmapp:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "Ledigt utrymme:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "SprÃ¥k:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Port för webbgrÀnssnitt:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Port för fjÀrrgrÀnssnitt:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Filhanterare" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "LÀgg till paket" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Klistra in lÀnkar eller ladda upp en container." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Namnet pÃ¥ det nya paketet." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "LÀnkar" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Klistra in dina lÀnkar eller valfri text och tryck filterknappen." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Filtrera lÀnkar" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "Lösenord för RAR-arkiv" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Fil" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "Ladda upp en container." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "LÀser captcha" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Captcha" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Skriv in texten pÃ¥ captchan." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "WebbgrÀnssnitt" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad uppdatering tillgÀnglig!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Plugins uppdaterade, starta om!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha vÀntar" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "Logga ut" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Administrera" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "Logga in!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Stoppa" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "HÀmta:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Ã
teranslut:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Hastighet:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Aktiv:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Uppdatera sidan" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "lÀser in" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Tillbaka upp" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "Avsluta pyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "Starta om pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "För att lÀgga till anvÀndare eller byta lösenord anvÀnd:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Viktigt: AdminanvÀndare har alltid alla behörigheter!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Byt lösenord" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "Behörigheter" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "Àndra" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Ange ditt nuvarande och önskade lösenord." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "AnvÀndare" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Nuvarande lösenord" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Nytt lösenord" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Det nya lösenordet." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Nytt lösenord (upprepa)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "Upprepa det nya lösenordet." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Du har inte behörighet att komma Ã¥t denna sida." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "HÀmtningskatalogen hittades inte." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "inte tillgÀnglig" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Kör pyload.py -s för att komma Ã¥t konfigurationen." + diff --git a/locale/sv/LC_MESSAGES/pyLoad.mo b/locale/sv/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 29d93d585..000000000 --- a/locale/sv/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/sv/LC_MESSAGES/pyLoad.po b/locale/sv/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..7b88d29f7 --- /dev/null +++ b/locale/sv/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Swedish\n" +"Language: sv_SE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "Tog emot avslutningssignal" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad körs redan med pid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Misslyckades att Àndra gruppen %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Kunde inte Àndra anvÀndaren: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "mapp för loggar" + +#: module/Core.py:340 +msgid "Starting" +msgstr "Startar" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "AnvÀnder hemkatalog: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "pyCrypto avkodar containerfiler" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "mapp för temporÀra filer" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "mapp för hÀmtningar" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "OpenSSL för sÀker anslutning" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Flyttar gamla anvÀndarinstÀllningar till databasen" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "Kontrollera dina login-uppgifter med './pyload.py -u'" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "Alla lÀnkar togs bort" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "HÀmtningstid: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "Ledigt utrymme: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Aktiverar konton..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Aktiverar tillÀggsprogram..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad Àr igÃ¥ng" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "startar om pyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyLoad avslutas" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "Installera %s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "kunde inte hitta %(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "kunde inte skapa %(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "stÀnger ner..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "fel vid nedstÀngning" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "dödade pyLoad frÃ¥n Terminal" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "Fildatabasen togs bort pÃ¥ grund av inkompatibel version." + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "Fildatabasen kunde INTE konverteras." + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "Databasen konverterades frÃ¥n v2 till v3." + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "Databasen konverterades frÃ¥n v3 till v4." + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "Konverterar gammal Django DB" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "fÀrdig" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "frÃ¥nkopplad" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "ansluten" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "kölagd" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "hoppades över" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "vÀntar" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "temp. frÃ¥nkopplad" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "startar" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "misslyckades" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "avbruten" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "dekrypterar" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "anpassad" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "hÀmtar" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "behandlar" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "okÀnd" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paketet klart: %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "AnvÀnder SSL ThriftBackend" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Fel i fjÀrradministrationsmodulen: %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "Startar %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "InlÀsningen av administrationsmodulen %(name)s misslyckades | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "vÀntar %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL-certifikat hittades inte." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Ledsen, start av %s direkt frÃ¥n pyLoad stöds inte lÀngre" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "Du kan " + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "naturligtvis kan du fortfarande anvÀda befintliga %s med pyLoads fastcgi server" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "exempel pÃ¥ konfigurationsfiler finns i mappen \"module/webui/servers\"" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "Kan inte anvÀnda %(server)s. python-flup Àr inte installerat!" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "Fel vid import av den lÀtta servern: %s" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "Du mÃ¥ste ladda ner och kompilera bjoern, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "Kopiera filen boern.so till mappen 'module/lib' eller anvÀnd 'setup.py install'" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "Naturligtvis behöver du vara bekant med Linux och veta hur man kompilerar programvara" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "Server instÀlld pÃ¥ trÃ¥dad, pga kÀnda prestandaproblem i Windows." + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Den hÀr servern anvÀnder inte SSL, övervÀg att anvÀnda den trÃ¥dade istÀllet " + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "Startar inbyggd webbserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "Startar trÃ¥dad SSL-webbserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "Startar trÃ¥dad webbserver: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "Startar fastcgi-server: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "Startar den lÀtta webservern (bjoern): %(host)s:%(port)d" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Du har inte behörighet att komma Ã¥t denna sida." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "HÀmtningskatalogen hittades inte." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "inte tillgÀnglig" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Kör pyload.py -s för att komma Ã¥t konfigurationen." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "HÀmtningen startar: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "HÀmtningen klar: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Plugin %s saknar en funktion." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "HÀmtningen avbröts: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "HÀmtning startades om: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "HÀmtningen Àr offline: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "HÀmtningen Àr tillfÀlligt offline: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "HÀmtning misslyckades: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "HÀmtning hoppades över: %(name)s pga %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "Avkrypteringen startar: %s" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "HÀmtning misslyckades: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "Försöker igen %s" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Misslyckades aktivera %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Aktiverade plugins: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Avaktivera plugins: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Ã
teranslutningen misslyckades: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Skript för att Ã¥teransluta hittades inte!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Startar reconnect" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Exekveringen av Ã¥teranslutningsskriptet misslyckades!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Ã
teransluten, nytt IP-nummer: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "OtillrÀckligt utrymme pÃ¥ enheten" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "Din tid %s har ett felaktigt format. AnvÀnd: 1:22-3:44" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "%s innehÃ¥ller ett ogiltigt mönster." + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Fel vid import av %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "lÀnklistan kunde inte raderas" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "KontoinstÀllningar raderade pga nytt format för konfigureringen." + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "Filen finns inte." + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "Aktiverat" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "Ingen plugin returnerade captcharesultat i tid." + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "Ingen klient för avkryptering av captcha ansluten" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "Lade till paketet %(name)s som innehÃ¥ller %(count)d lÀnkar" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "Lade till %(count)d lÀnkar till paket #%(package)d " + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Ingen js motor hittades. Var vÀnlig installera Spidermonkey, ossp-js, pyv8 eller rhino" + diff --git a/locale/sv/LC_MESSAGES/pyLoadCli.mo b/locale/sv/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index f0c2c04bd..000000000 --- a/locale/sv/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/sv/LC_MESSAGES/pyLoadCli.po b/locale/sv/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..028585bc6 --- /dev/null +++ b/locale/sv/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Swedish\n" +"Language: sv_SE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " KommandoradsgrÀnssnitt" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s hÀmtningar:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Hastighet: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " Storlek: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " FÀrdig om: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "vÀntar: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Meny:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " LÀgg till lÀnkar" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " Hantera kö" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "Hantera lÀnksamlaren" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "Pausa/starta servern" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " Döda server" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " Avsluta" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "AnvÀnd denna syntax: add <paketnamn> <lÀnk> <lÀnk2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Kontrollerar %d lÀnkar:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Filen finns inte." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad avbröts" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Visar serverstatus" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Visar nedladdningar i kön" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Visar nedladdningar i lÀnksamlaren" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "LÀgger till paketet i kön" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "LÀgger till paketet i lÀnksamlaren" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Radera filer frÃ¥n kön/lÀnksamlaren" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Radera paket frÃ¥n kön/lÀnksamlaren" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Flytta paket frÃ¥n kön till lÀnksamlaren och vice versa" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Starta om filer" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Starta om paket" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Undersök onlinestatus, fungerar med lokal container" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Kontrollerar onlinestatusen för en containerfil" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Pausa servern" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "Ã¥teruppta hÀmtningar" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Pausa/fortsÀtt" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "döda server" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Lista över kommandon:" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Kunde inte skriva anvÀndarens instÀllningsfil" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "Du behöver py-openssl för att ansluta till denna pyLoad Core." + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adress: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "AnvÀndarnamn: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Lösenord: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "Inloggningsdata Àr felaktigt." + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "Kunde inte etablera anslutning till %(addr)s:%(port)s." + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "Du behöver py-openssl för att ansluta till denna pyLoad core." + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Interaktivt lÀge ignorerat dÃ¥ vissa kommandon skickades." + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "LÀgg till paket:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Ange ett namn för nya paketet" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Paket: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Klistra in lÀnkarna som du vill lÀgga till." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Skriv %s nÀr du Àr fÀrdig." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "LÀnkar lades till: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr " tillbaka till huvudmenyn" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Hantera paket:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Hantera lÀnkar:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Vad vill du flytta?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Vad vill du ta bort?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Vad vill du starta om?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "VÀlj vad du vill göra eller skriv in ett paketnummer." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "ta bort" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "flytta" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "starta om" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - föregÃ¥ende" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr " - nÀsta" + diff --git a/locale/sv/LC_MESSAGES/pyLoadGui.mo b/locale/sv/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 4231a1bbf..000000000 --- a/locale/sv/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/sv/LC_MESSAGES/setup.mo b/locale/sv/LC_MESSAGES/setup.mo Binary files differdeleted file mode 100644 index 2cf2efd70..000000000 --- a/locale/sv/LC_MESSAGES/setup.mo +++ /dev/null diff --git a/locale/sv/LC_MESSAGES/setup.po b/locale/sv/LC_MESSAGES/setup.po new file mode 100644 index 000000000..190b6ab71 --- /dev/null +++ b/locale/sv/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Swedish\n" +"Language: sv_SE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "j" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "VÀlkommen till konfigurationsguiden för pyLoad." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Den kommer att kontrollera ditt system och göra en grundkonfiguration för att kunna köra pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "VÀrden inom hakparanteser [] Àr alltid standardvÀrdet," + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "tryck bara Enter i de fall du inte vill Àndra det eller om du Àr osÀker vad du ska vÀlja." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Glöm inte: Du kan alltid köra denna guide igen med --setup eller parametern -s, nÀr du startar pyload.py ." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Om du fÃ¥r nÃ¥gra problem med denna guide sÃ¥ tryck Ctrl-C," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "för att avbryta och lÃ¥t bli att starta automatiskt med pyload.py ." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "Tryck pÃ¥ Enter nÀr du Àr fÀrdig för att kontrollera systemet." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "Du behöver pycurl, sqlite och python 2.5, 2.6 eller 2.7 för att köra pyLoad." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "Korrigera detta och kör pyLoad igen." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "Konfigurationen kommer nu att stÀngas." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Systemkontrollen Àr fÀrdig. Tryck pÃ¥ Enter för att se din statusrapport." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "container-dekryptering" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "ssl-anslutning" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "automatisk captcha-dekryptering" + +#: module/setup.py:104 +msgid "GUI" +msgstr "Grafiskt grÀnssnitt" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "WebbgrÀnssnitt" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "utökad Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "Funktioner tillgÀngliga:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Funktioner saknade: " + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "ingen py-crypto tillgÀnglig" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "Du behöver denna om du vill dekryptera container-filer." + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "ingen SSL tillgÀnglig" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Denna krÀvs om du vill etablera en sÀker anslutning till core eller webbgrÀnssnittet." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "Om du endast vill ha lokalt Ã¥tkomst till pyLoad sÃ¥ Àr inte SSL anvÀndbart." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "ingen Captcha Recognition tillgÀnglig" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "Behövs endast för vissa \"hosters\" och som \"freeuser\"." + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "GUI inte tillgÀngligt" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "Grafiskt anvÀndargrÀnssnitt." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "ingen JavaScript-motor hittades" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Du behöver detta för nÃ¥gra Click'N'Load-lÀnkar. Installera Spidermonkey, ossp-js, pyv8 eller rhino" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Du kan avbryta konfigurationen nu och rÀtta till beroenden om du vill." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "FortsÀtt med konfigurationen?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Vill du Àndra konfigurationssökvÀgen? Aktuell sökvÀg Àr %s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "Om du anvÀnder pyLoad pÃ¥ en server eller hempartitionen finns pÃ¥ en intern Flash-disk sÃ¥ kan det vara en bra idé att Àndra den." + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Ãndra konfigurationssökvÀg?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "Vill du konfigurera inloggningsdata och grundinstÀllningar?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Detta rekommenderas för första gÃ¥ngen." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Skapa grundkonfiguration?" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Vill du konfigurera SSL?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Konfigurera SSL?" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Vill du konfigurera webbgrÀnssnittet?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Konfigurera webbgrÀnssnittet?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Konfigurationen fÀrdigstÀlldes." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Tryck Enter för att avsluta och starta om pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Systemkontroll ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Din python-version Àr för ny. AnvÀnd Python 2.6/2.7" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Din python-version Àr för gammal. AnvÀnd minst Python 2.5" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Python-version: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "Din installerade jinja2 version %s verkar vara för gammal." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "Du kan med sÀkerhet fortsÀtta men om webbgrÀnssnittet inte fungerar," + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "uppgradera eller avinstallera det. pyLoad inkluderar ett lÀmpligt jinja2-bibliotek." + +#: module/setup.py:264 +msgid "JS engine" +msgstr "JS-motor" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Grundkonfiguration ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "Följande inloggningsdata Àr giltigt för CLI, GUI och webbgrÀnssnitt." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "Externa klienter (GUI, CLI osv) behöver fjÀrrÃ¥tkomst för att fungera över nÀtverket." + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "Men om du bara vill anvÀnda webbgrÀnssnittet kan du avaktivera den för att spara RAM." + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Aktivera fjÀrrÃ¥tkomst" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "HÀmtningsmapp" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Max samtidiga hÀmtningar" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "AnvÀnd Ã¥teranslutning (Reconnect)?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Plats för Reconnect-skript" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Konfiguration av webbgrÀnssnitt ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Aktivera webbgrÀnssnitt?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Lyssningsadress, om du anvÀnder 127.0.0.1 eller localhost, kommer webbgrÀnssnittet endast vara Ã¥tkomligt lokalt." + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad erbjuder flera server backends. HÀr följer en kort förklaring." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "Standardserver, bÀsta valet om du inte vet vilken du ska vÀlja." + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "Denna server erbjuder SSL och Àr ett bra alternativ till den inbyggda." + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Kan anvÀndas med apache, lighttpd. KrÀver att du konfigurera dem, vilket inte Àr sÃ¥ svÃ¥rt." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "Mycket snabbt alternativ skrivet i C. KrÀver libev och Linux-kunskaper." + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "HÀmta det hÀr: https://github.com/jonashaag/bjoern, kompilera det" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "och kopiera bjoern.so till module/lib" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Viktigt: I vissa ovanliga fall kanske den inbyggda servern inte fungerar. Om du upplever problem med webbgrÀnssnittet" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "sÃ¥ kom tillbaka hit och Àndra den inbyggda servern till den trÃ¥dade servern." + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## SSL-konfiguration ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Kör dessa kommandon frÃ¥n konfigurationsmappen för pyLoad för att skapa SSL-certifikaten:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "Du kan aktivera SSL nu om du Àr fÀrdig och allting gick bra." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "Aktivera SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "VÀlj Ã¥tgÀrd" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Skapa/Redigera anvÀndare" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Lista anvÀndare" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Ta bort anvÀndare" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - Avsluta" + +#: module/setup.py:376 +msgid "Users" +msgstr "AnvÀndare" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "StÀller in ny konfigurationssökvÀg. Aktuell konfiguration kommer inte att överföras!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "KonfigurationssökvÀg" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "KonfigurationssökvÀgen har Àndrats. Guiden kommer nu att stÀngas. Starta om för att fortsÀtta." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Tryck Enter för att avsluta." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "InstÀllning av konfigurationssökvÀg misslyckades: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: saknas" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Lösenord: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Lösenord (igen): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Lösenorden stÀmde inte överens." + +#: module/setup.py:493 +msgid "yes" +msgstr "ja" + +#: module/setup.py:493 +msgid "true" +msgstr "sant" + +#: module/setup.py:493 +msgid "t" +msgstr "s" + +#: module/setup.py:496 +msgid "no" +msgstr "nej" + +#: module/setup.py:496 +msgid "false" +msgstr "falskt" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Ogiltig inmatning" + diff --git a/locale/te/LC_MESSAGES/django.po b/locale/te/LC_MESSAGES/django.po new file mode 100644 index 000000000..08637a88d --- /dev/null +++ b/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Telugu\n" +"Language: te_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/te/LC_MESSAGES/pyLoad.po b/locale/te/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..9b38dd6fa --- /dev/null +++ b/locale/te/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Telugu\n" +"Language: te_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/te/LC_MESSAGES/pyLoadCli.po b/locale/te/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..8bea11172 --- /dev/null +++ b/locale/te/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Telugu\n" +"Language: te_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/te/LC_MESSAGES/setup.po b/locale/te/LC_MESSAGES/setup.po new file mode 100644 index 000000000..3a58338b3 --- /dev/null +++ b/locale/te/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 06:29-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Telugu\n" +"Language: te_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "" + +#: module/setup.py:313 +msgid "Port" +msgstr "" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/tr/LC_MESSAGES/django.po b/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 000000000..e76b54f38 --- /dev/null +++ b/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Turkish\n" +"Language: tr_TR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "Yeni Captcha İsteÄi" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "LÃŒtfen captcha ÃŒstÃŒndeki metni okuyunuz." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoad yeniden baÅlatıldı" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "Kapat" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "BaÅarılı" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "Aç" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "pyLoad'dan çıkmak istediÄinize emin misiniz?" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "BaÄlantıyı yeniden baÅlat" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "BaÄlantıyı Sil" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "LÃŒtfen paket adını girin." + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "LÃŒtfen saÄdaki captcha ya tıklatın." + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "Bir hata oluÅtu." + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "Klasör boÅ" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "BaÅarısız oldu" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "Okumak için Captcha bulunamadı" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "Parolalar eÅleÅmedi." + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "Ayarlar kaydedildi." + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "Yeni klasör" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "pyLoad'u yeniden baÅlatmak istediÄinize emin misiniz?" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "bekleyen %s" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "Aktif İndirmeler" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "Ev" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "İndirmeler" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "Loglar " + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "Ayarlar" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "İsim" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Durum" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "Bilgi" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "Boyut" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "İlerleme" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "Oturum açma" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Kullanıcı Adı" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Åifre" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "Kullanıcı adınız ve parolanız uymuyor. LÃŒtfen tekrar deneyiniz." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "Hesabınızı sıfırlamak için veya yeni kullanıcı eklemek için çalıÅtırın:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "Bitenleri Temizle" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "BaÅarısızları Tekrar BaÅlat" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "Klasör:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "Åifre:" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "Paketi DÃŒzenle" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "AÅaÄıdaki paket detaylarını dÃŒzenle." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "Paketin adı." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Klasör" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "Bu indirmeler için alt klasör adı." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "Unrar için parola listesi." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Gönder" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "Sıfırla" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "BaÅarılı Åekilde çıkıŠyaptınız." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "Yol" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "tam" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "BaÄıntılı" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "isim" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "boyut" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "tip" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "son deÄiÅimi" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "ana klasör" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "içerik yok" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Genel" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "Eklentiler" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Hesaplar" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "MenÃŒden bir bölÃŒm seçiniz" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Eklenti" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "Son geçerlilik tarihi" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "Kalan trafik" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "Zaman" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "Maks Paralel" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "Sil?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "geçerli" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "geçersiz" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "evet" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "hayır" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Ekle" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "Hesap Ekle" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "Premium özelliklerini kullanabilmek için hesap bilgilerini giriniz." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "Kullanıcı adınız." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "Bu hesap için parola." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "TÃŒrÃŒ" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "Hesabınız için host seçiniz." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "BaÅla" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "önceki" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "sonraki" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "Son" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "Haberler" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "Destek" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "Sistem" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad versiyonu:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "Kurulum KlasörÃŒ:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "Ayar KlasörÃŒ:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "İndirme KlasörÃŒ:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "BoÅ Alan:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "Dil:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Web ArayÃŒz Portu:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "Uzak ArayÃŒz Portu:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "Kurulum" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "Dosya Yöneticisi" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "Paket Ekle" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "Linklerinizi yapıÅtırın veya taÅıyıcı dosyayı yÃŒkleyin." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "Yeni paketin adı." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "Linkler" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "Linklerinizi veya herhangi bir metni yapıÅtırıp filitrele butonuna basınız." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "Linkleri filitrele" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "RAR-ArÅiv dosyaları için parola" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "Dosya" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "TaÅıyıcı dosyayı yÃŒkleyin." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Hedef" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "Captcha okunuyor" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "Captcha." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "Metin" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "Captcha ÃŒstÃŒndeki metni giriniz." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Kapat" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Web arayÃŒzÃŒ" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad GÃŒncelleme mevcut!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "Eklentiler gÃŒncellendi, lÃŒtfen yeniden baÅlatın !" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "Captcha bekliyor" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "ÃıkıÅ" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "Yönet" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "Bilgi" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "LÃŒtfen GiriÅ Yapın!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "Dur" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "İptal" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "İndirme:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "Yeniden baÄlan:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "Hız:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "Aktif:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "Sayfayı yenile" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "yÃŒkleniyor" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "Sayfa baÅı" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "pyLoad'dan çık" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "pyLoad'ı yeniden baÅlat" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "Kullanıcı eklemek veya Åifre deÄiÅtirmek:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "Ãnemli: Yönetici kullanıcısının her zaman tÃŒm izinleri vardır!" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "Parolayı DeÄiÅtir" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "İzinleri" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "deÄiÅtir" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "Åimdiki parolanızı ve deÄiÅtirmek istediÄiniz parolayı giriniz." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "Kullanıcı" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "Parolanız" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "Yeni parola" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "Yeni parola." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "Yeni parola (tekrar)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "LÃŒtfen yeni parolanızı tekrar giriniz." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Bu sayfaya eriÅmek için izniniz yok." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "İndirme dizini bulunamadı." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "sınırsız" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "mevcut deÄil" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Ayarlara eriÅmek için pyload.py -s çalıÅtırın." + diff --git a/locale/tr/LC_MESSAGES/pyLoad.mo b/locale/tr/LC_MESSAGES/pyLoad.mo Binary files differdeleted file mode 100644 index 2c20cfbd4..000000000 --- a/locale/tr/LC_MESSAGES/pyLoad.mo +++ /dev/null diff --git a/locale/tr/LC_MESSAGES/pyLoad.po b/locale/tr/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..c3d2d7a55 --- /dev/null +++ b/locale/tr/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Turkish\n" +"Language: tr_TR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "ÃıkıŠsinyali alındı" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoad zaten %s pid ile çalıÅıyor" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "Grup deÄiÅtirme baÅarısız: %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "Kullanıcı deÄiÅtirme baÅarısız: %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "gÃŒnlÃŒkler için klasör" + +#: module/Core.py:340 +msgid "Starting" +msgstr "BaÅlıyor" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "Ev dizinini kullan: %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "geçici dosyalar için klasör" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "indirmeler için klasör" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "GÃŒvenli baÄlantı için OpenSSL" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "Eski kullanıcı ayarlarını veritabanına taÅı" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "GiriÅ bilgilerinizi kontrol edin ./pyload.py -u" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "TÃŒm baÄlantılar kaldırıldı" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "İndirme sÃŒresi: %s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "BoÅ alan: %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "Hesap etkinleÅtiriliyor ..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "Eklentiler etkinleÅtiriliyor ..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoad baÅlatıldı ve çalıÅıyor" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "pyLoad yeniden baÅlatılıyor" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "pyload çıkıÅ" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "kapatılıyor ..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "kapatma sırasında hata oluÅtu" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "bitti" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "ÃevrimdıÅı" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "Ãevrimiçi" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "sıraya alındı" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "atlandı" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "bekliyor" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "geçici çevrimdıÅı" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "baÅlatılıyor" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "baÅarısız oldu" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "iptal edildi" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "çözÃŒlÃŒyor" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "Ãzel" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "indiriliyor" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "iÅlem devam ediyor" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "bilinmeyen" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "Paket tamamlandı. %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "Uzak uç hatası: % s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "BaÅlıyor %(name)s: %(addr)s:%(port)s" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "Arka uç yÃŒklenirken hata %(name)s | %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "bekleyen %s" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL sertifikaları bulunamadı." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "Maalesef pyLoad içinde doÄrudan baÅlangıçââ %s için destek dÃŒÅtÃŒ" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "bjoern'i indirmek ve derlemek gerekir, https://github.com/jonashaag/bjoern" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "Bu sunucu hiçbir SSL sunmuyor, kullanarak yerine diÅli dÃŒÅÃŒnÃŒn lÃŒtfen" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "YerleÅik web sunucusu baÅlatılıyor: %(host)s:%(port)d" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "Bu sayfaya eriÅmek için izniniz yok." + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "İndirme dizini bulunamadı." + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "sınırsız" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "mevcut deÄil" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "Ayarlara eriÅmek için pyload.py -s çalıÅtırın." + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "KarÅıdan yÃŒkleme baÅarısız, tekli baÄlantıya dönÃŒn | %s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "YÃŒkleme baÅlar: %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "YÃŒkleme bitti: %s" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "Eklenti %s iÅlevi eksik." + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "YÃŒkleme iptal edildi: %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "YÃŒkleme yeniden baÅlatıldı: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "YÃŒkleme çevrimdıÅı: %s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "YÃŒkleme geçici olarak çevrımdıÅı: %s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "YÃŒkleme baÅarısız: %(name)s | %(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "Sunucuya baÄlanılamadı veya baÄlantı sıfırlandı, 1 dakikalık erteleme bekleniyor." + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "YÃŒkleme atlandı: %(name)s bunun yÃŒzÃŒnden %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "Bilgisi %(name)s alınırken hata | %(err)s oluÅtu" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "Aktive etme baÅarısız %(name)s" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "Eklentiler etkinleÅtiriliyor: %s" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "Eklentiler kapatılıyor: %s" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "Tekrar baÄlanma baÅarısız: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "Tekrar baÄlanma komutu bulunamadı!" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "Tekrar baÄlanma baÅlatılıyor" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "Yeniden BaÄlantı komut dosyası yÃŒrÃŒtmesi baÅarısız!" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "Yeniden BaÄlandı, yeni IP: %s" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "Aygıtta yeterli alan yok" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "Hesap ile giriÅ yapılamadı %(user)s | %(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "Hatalı Åifre" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "Hesap %s yeterli trafik yok, 30 dk içinde yeniden deneyin" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "Hesap %s sÃŒresi doldu, 1 saat içinde yeniden deneyin" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "İndirme sınırına eriÅildi" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "Alınırken hata %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "Hiçbir Sunucu yÃŒklenemedi" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "Bitshare hesabınızdaki direk yÃŒklemeyi aktifleÅtirin" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "Yetkilendirme gerekli (kullanıcı adı: Åifre)" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "LÃŒtfen %s hesabınıza girin veya bu eklentiyi devre dıÅı bırakın" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "İndirilen dosyadaki (%s)... HTML kodunda yönlendirme hatası? Download yeniden baÅlatıldı." + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "Dosya geçici olarak kullanılamıyor" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "Netload: YÃŒklemeler %d s arasında bekliyor." + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "Netload: captcha için bekleniyor %d s." + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "İndirilen dosya boÅ" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "API anahtarı geçersiz" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: yeterli trafik kalmadı" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "Trafik aÅıldı" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "Rapidshare: Trafik PaylaÅılan (direk yÃŒkleme)" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "Zaten bu IP adresinden yÃŒkleme yapılmakta, 60 saniye bekleniyor" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "Geçersiz kimlik doÄrulama kodu, yÃŒkleme yeniden baÅlatılacak" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "RapidShareCom: TÃŒm ÃŒcretsiz baÄlantılar doldu" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "Bu dosya için premium ÃŒyelik hesabı gerekir" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "Dosya adı geçersiz bildirdi" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "Paralel yÃŒkleme hatası, 60 saniye bekleniyor." + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "giriÅ yapılmadı." + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "ÃözÃŒmleme baÅarısız oldu" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "URL'de saÄlanan hiçbir dosya anahtarı yok" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "Hata kodu:" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "*** Eklentiler gÃŒncellendi, pyLoad'ı yeniden baÅlatın ***" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "Eklentiler gÃŒncellendi ve yeniden yÃŒklendi" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "Eklentiler için gÃŒncelleme yok" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "pyLoad için gÃŒncelleme yok" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "*** Yeni pyLoad SÃŒrÃŒmÃŒ %s mevcuttur ***" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** Buradan indirin: http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "GÃŒncelleÅtirmeler için sunucuya baÄlanmak mÃŒmkÃŒn deÄil" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "Yeni versiyonu %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "%s gÃŒncelleÅtirme hatası" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "SÃŒrÃŒm uyuÅmazlıÄı" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "YÃŒkleme bitti: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "Yeni Captcha İsteÄi: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "captcha ÃŒstÃŒndeki 'c %s metnini cevapla" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "LÃŒtfen önce premium.to hesabınızı ekleyin ve pyLoad'u yeniden baÅlatın" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "HotFolder gelen ek %s" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "YÃŒklÃŒ %s yok" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "%s etkinleÅtirilemedi" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "EtkinleÅtirildi" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "Aktif Extract eklentisi yok" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "%s paketini daha sonra ayıklamak için sıraya alındı" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "%s paketi kontrol et" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "ArÅiv ayıklanıyor Åuraya %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "ArÅivden ayıklanacak dosya bulunamadı" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "Ayıklanıyor" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "Åifre korumalı" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "Hatalı Åifre" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "%s Dosya siliniyor" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "Ayıklama bitti" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "ArÅiv hatası" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRC UyuÅmazlıÄı" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "Bilinmeyen Hata" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "Kullanıcı ve Grup Ayarları baÅarısız oldu" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: Port 9666 zaten kullanılıyor" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "%s kredi kaldı" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "yanıt gönderilemedi." + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "Sizin CaptchaTrader hesabınızda yeterli kredi bulunmamakta" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "Åifreleme listesi bulunamadı" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Åifreleme listesi boÅ" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "YÃŒkleme bitti: %(name)s @ %(plugin)s " + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "Yeni CaptchaID yÃŒkleme tarafından: %s : %s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "Captcha 9kw.eu hesabı yeterli kredi yok" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "%s: için yÃŒklÃŒ komut dosyaları" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "Komut dosya çalıÅtırılamaz:" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "Hata %(script)s: %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "ExpertDecoders hesabınızda yeterli kredi yok" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "LÃŒtfen önce rehost.to hesabınızı ekleyin ve pyLoad'u yeniden baÅlatın" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "LÃŒtfen önce bir geçerli premiumize.me hesabı ekleyin ve pyLoad yeniden baÅlatın." + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "%d kredi kaldı" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "Captcha Åifresini çözmek için pil ve tesseract yÃŒklenmemiÅ ve hiçbir istemci baÄlı deÄil" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "Kullanıcı ve grup kurma baÅarısız oldu: %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/tr/LC_MESSAGES/pyLoadCli.mo b/locale/tr/LC_MESSAGES/pyLoadCli.mo Binary files differdeleted file mode 100644 index 30e94695b..000000000 --- a/locale/tr/LC_MESSAGES/pyLoadCli.mo +++ /dev/null diff --git a/locale/tr/LC_MESSAGES/pyLoadCli.po b/locale/tr/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..19d122f60 --- /dev/null +++ b/locale/tr/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Turkish\n" +"Language: tr_TR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " Komut satır arayÃŒzÃŒ" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s İndirmeler:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " Hız: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " BÃŒyÃŒklÃŒk: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " BitiÅ zamanı: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "ID:" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "bekleniyor: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "Durum" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "Duraklatıldı" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "çalıÅıyor" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "toplam hız" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "Sıradaki Dosyalar" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "Toplam" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "MenÃŒ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " Linkleri Ekle" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "KuyruÄu DÃŒzenle" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "KolektörÃŒ DÃŒzenle " + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "(Un)Sunucuyu Durdur" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "Sunucuyu DevredıÅı bırak" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "ÃıkıÅ" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "LÃŒtfen doÄru eÅleÅtirme metnini kullanın:Ekle <Paket adı> <link> <linkl2>" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "%d Linkler Kontrol ediliyor" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Dosya bulunamadı" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad durdu" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "Sunucu durumunu yazdır" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "Kuyruktakileri yazdır" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "Kolektördekileri yazdır" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "KuyruÄa paket ekle" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "Kolektöre paket ekle" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "Dosyaları Kuyruktan/Kolektör'den sil" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "Paketleri Kuyruktan/Kolektör'den sil" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "Paketleri Kuyruktan , Kolektöre taÅı veya tam tersini yap" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Dosyaları yenile" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "Paketleri yenile" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "Yerel konteynerla çalıÅtıgını ve online olup olmadıÄını kontrol et" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "Konteyner dosyalarının çemrimiçi oldugunu kontrol et" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "Sunucuyu durdur" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "indirmelere devam et" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "Seçilenleri durdur/devam ettir" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "sunucuyu durdur yap" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "Komut listesi" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "Kullanıcı ayar dosyası yazılamadı" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "pyLoad çekirdeÄine baÄlanmak için py-opensll ye baglanmanız lazım" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Adres: " + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Port:" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Kullanıcı adı: " + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Åifre: " + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "GiriÅ bilgileri yanlıÅ" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "%(addr)s:%(port)s. ile baÄlantı kurulamadı" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "pyLoad çekirdeÄine baÄlanmak için py-opensll ye baglanmanız lazım" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "Bazı komutları onayladınızdan beri , ÃevrimdıÅı modu engellendi" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "Paket ekle:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "Yeni paketin adını girin" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Paket: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Eklemek isteniz linkleri çözÃŒmle" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Tip %s tamamlandı" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Eklenen linkler: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "MenÃŒye geri dön" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "Paketleri DÃŒzenle:" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Linkleri DÃŒzenle:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "Neleri taÅımak istersiniz?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "Neleri silmek istersiniz?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "Neleri yenilemek istersiniz?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "Ne yapmak istediniz seçin veya paket numarası girin." + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "sil" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "taÅı" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "yeniden baÅlat " + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - önceki" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "-Sonraki" + diff --git a/locale/tr/LC_MESSAGES/pyLoadGui.mo b/locale/tr/LC_MESSAGES/pyLoadGui.mo Binary files differdeleted file mode 100644 index 1ae24953f..000000000 --- a/locale/tr/LC_MESSAGES/pyLoadGui.mo +++ /dev/null diff --git a/locale/tr/LC_MESSAGES/setup.po b/locale/tr/LC_MESSAGES/setup.po new file mode 100644 index 000000000..e12e79344 --- /dev/null +++ b/locale/tr/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Turkish\n" +"Language: tr_TR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "e" + +#: module/setup.py:53 +msgid "n" +msgstr "h" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "PyLoad ayar sihirbazına hoÅgeldiniz." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "Sisteminizi kontrol edecek ve pyLoad'ın çalıÅması için bir temel kurulum yapacaktır." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "Parantez içindeki deÄerler [], her zaman varsayılan deÄerdir" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "deÄiÅtirmek istemediÄinde yada neyi seçeceÄinden emin deÄilsen, sadece enter'e bas." + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "Unutma: pyload.py -setup yada -s ekleyerek bu Asistanı her zaman yeniden baÅlatabilirsiniz." + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "Asistan ile herhangi bir sorun yaÅarsanız STRG-C tuÅuna basın," + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "iptal etmek ve pyload.py ile otomatik baÅlatmamak için." + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "EÄer sistem kontrolÃŒ için hazırsanız, enter'a basın." + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "pyLoad'ı çalıÅtırmak için pycurl, sqlite ve python 2.5, 2.6 veya 2.7 gerekir." + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "LÃŒtfen bunu dÃŒzeltin ve pyLoad'ı yeniden çalıÅtırın." + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "Kur Åimdi kapanacak." + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "Sistem kontrolÃŒ tamamlandı, durum raporunu görmek için Enter tuÅuna basın." + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "## Durum ##" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "ssl baÄlantısı" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "ArayÃŒz" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Web arayÃŒzÃŒ" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "geniÅletilmiÅ Click'N'Load" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "Mevcut Ãzellikler:" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "Eksik Ãzellikler:" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "SSL bulunmamaktadır" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "Sisteme yada Web arayÃŒzÃŒne gÃŒvenli baÄlantı için bu gerekli." + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "pyLoad'a yanlızca yerel eriÅmek istiyorsanız, ssl önerilmez." + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "Kullanıcı ArayÃŒzÃŒ mevcut deÄil" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "Grafiksel Kullanıcı ArayÃŒzÃŒ." + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "JavaScript motoru bulunamadı" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "Bazı Click'N'Load baÄlantıları için gerekli. Spidermonkey, ossp-js, pyv8 yada rhino yÃŒkleyin" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "Åuan kurulum iptal edebilir ve gerekiyorsa bazı baÄımlılık gerektiren dÃŒzeltmeleri yapabilirsiniz." + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "Kurulum ile devam edilsin mi?" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "Yapılandırma yolunu deÄiÅtirmek istiyor musunuz? Mevcut% s" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "Yapılandırma yolunu deÄiÅtirme?" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "GiriÅ verileri ve temel ayarları yapılandırmak istiyor musunuz?" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "Bu ilk çalıÅma için tavsiye edilir." + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "Temel kurulum yap" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "Ssl yapılandırmak istiyor musunuz?" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "Ssl yapılandırması" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "Web arayÃŒzÃŒnÃŒ yapılandırmak istiyor musunuz?" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "Web arayÃŒzÃŒ yapılandırması?" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "Kur baÅarıyla tamamlandı." + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "Ãıkmak için Enter tuÅuna basın ve pyLoad'ı yeniden baÅlatın" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "## Sistem Kontrol ##" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "Python sÃŒrÃŒmÃŒnÃŒz çok yeni, Python 2.6/2.7 kullanın" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "Python sÃŒrÃŒmÃŒnÃŒz çok eski, en az Python 2.5 kullanın" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "Python Versiyon: OK" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "YÃŒklÃŒ olan Jinja2 versiyonu %s çok eski görÃŒnÃŒyor." + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "JS motoru" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "## Temel Kurulum ##" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "AÅaÄıdaki giriÅ verileri geçerlidir Åunlar için CLI, GUI ve webarayÃŒzÃŒ." + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Kullanıcı Adı" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "Uzaktan EriÅim" + +#: module/setup.py:291 +msgid "Language" +msgstr "Dil" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "İndirme klasörÃŒ" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "Max indirme sayısı" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "BaÄlantı sıfırlama?" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "Komut dosyası konumu yeniden baÄlanın" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "## Web arayÃŒzÃŒ Kurulumu ##" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "Web arayÃŒzÃŒ etkin?" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "Adrese bak, eÄer 127.0.0.1 veya localhost kullanıyorsanız, webinterface yerel olarak eriÅilebilir olacaktır." + +#: module/setup.py:312 +msgid "Address" +msgstr "Adres" + +#: module/setup.py:313 +msgid "Port" +msgstr "Port" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoad Åimdi kısa bir açıklama sonrasında, birçok sunucu arka uçları sunmaktadır." + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "Tarafından kullanılabilmek için apache, lighttpd, sana onları konfigÃŒre etmek gerektirir; ki bu çok da kolay bir iÅ deÄildir." + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "Buradan edinin: https://github.com/jonashaag/bjoern, onu derleyin" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "Dikkat: Bazı farklı durumlarda yerleÅik sunucu çalıÅmıyorsa, eÄer webarayÃŒzÃŒyle ilgili problem farke edersen" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "Buraya gel ve burada yerleÅik sunucu diÅli deÄiÅtir." + +#: module/setup.py:329 +msgid "Server" +msgstr "Sunucu" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "## SSL Kurulumu ##" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "Bu komutlar ssl sertifikaları yapmak için pyLoad config klasörÃŒnden çalıÅtırın:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "EÄer yaptıysan ve her Åey iyi gittiyse, ssl'yi Åimdi etkinleÅtirebilirsiniz." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "SSL EtkinleÅtir?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "Eylem seçin" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - Kullanıcı OluÅtur / DÃŒzenle" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - Kullanıcıları listele" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - Kullanıcı kaldır" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - ÃıkıÅ" + +#: module/setup.py:376 +msgid "Users" +msgstr "Kullanıcılar" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "Yeni ayarlar yapılandırma yolu, eski ayarlar transfer edilmeyecek!" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "Yapılandırma yolu" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "Yapılandırma yolu deÄiÅti, kurulum Åimdi kapanacak, devam etmek için yeniden baÅlatın." + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "Ãıkmak için Enter tuÅuna basın." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Yapılandırma ayar yolu baÅarısız oldu: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "%s: eksik" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Åifre: " + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "Åifre çok kısa. En az 4 sembol kullanın." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "Åifre (tekrar):" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "Parolalar eÅleÅmedi." + +#: module/setup.py:493 +msgid "yes" +msgstr "evet" + +#: module/setup.py:493 +msgid "true" +msgstr "doÄru" + +#: module/setup.py:493 +msgid "t" +msgstr "d" + +#: module/setup.py:496 +msgid "no" +msgstr "hayır" + +#: module/setup.py:496 +msgid "false" +msgstr "yanlıÅ" + +#: module/setup.py:496 +msgid "f" +msgstr "y" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "Geçersiz giriÅ" + diff --git a/locale/uk/LC_MESSAGES/django.po b/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 000000000..388d61f64 --- /dev/null +++ b/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "вОкл" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "вкл" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "ÐевЎалП" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "ÐÐŒâÑ" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "СÑаÑÑÑ" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "РПзЌÑÑ" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "ÐПгÑМ" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "ÐÐŒ'Ñ ÐºÐŸÑОÑÑÑваÑа" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "ÐаÑПлÑ" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Ðапка" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "ÐÑÐŽÑвеÑЎОÑО" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "ÐагалÑМÑ" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "ÐблÑÐºÐŸÐ²Ñ Ð·Ð°Ð¿ÐžÑО" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "ÐлагÑМ" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "ÐŽÑйÑМОй" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "ÐПЎаÑО" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "ТОп" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "СОÑÑеЌа" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "ÐаÑаЌеÑÑО" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "ÐÑОзМаÑеММÑ" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "ÐакÑОÑО" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "СкаÑÑваÑО" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "ÐÐŽÐŒÑМ" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "МеПбЌежеМОй" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/uk/LC_MESSAGES/pyLoad.po b/locale/uk/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..2c1e6af57 --- /dev/null +++ b/locale/uk/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "SSL-ÑеÑÑОÑÑкаÑО Ме зМайЎеМП." + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "МеПбЌежеМОй" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/uk/LC_MESSAGES/pyLoadCli.po b/locale/uk/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..57cb147ef --- /dev/null +++ b/locale/uk/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr " ÐМÑеÑÑÐµÐ¹Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ³ÐŸ ÑÑЎка" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s заваМÑажеМÑ:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr " КвОЎкÑÑÑÑ: " + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr " РПзЌÑÑ: " + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr " ÐакÑМÑОв Ñ: " + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "ID: " + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "ПÑÑкÑваММÑ: " + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "СÑаМ:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "пÑОзÑпОМеМП" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "загалÑМа ÑвОЎкÑÑÑÑ" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "ЀайлО Ñ ÑеÑзÑ" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "ÐÑÑПгП" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "ÐеМÑ:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr " ÐПЎаÑО пПÑОлаММÑ" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr " ÐеÑÑÐ²Ð°ÐœÐœÑ ÑеÑгПÑ" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr " ÐеÑÑваÑО кПлекÑПÑПЌ" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr " ÐбОÑО ÑеÑвеÑ" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr " ÐОйÑО" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "ÐÑÐŽÑ Ð»Ð°Ñка, вОкПÑОÑÑПвÑйÑе ÑакОй ÑОМÑакÑОÑ: ЎПЎаÑО < ÑÐŒ'Ñ ÐакеÑа > <link><link2>..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "ÐеÑевÑÑка %d пПÑОлаММÑ:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Ѐайл Ме ÑÑМÑÑ." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "ÐеÑеЌÑÑÑОÑО пакÑМкО з ÑеÑгО Ñ ÐºÐŸÐ»ÐµÐºÑÐŸÑ Ñ ÐœÐ°Ð²Ð¿Ð°ÐºÐž" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "ÐПЎаÑО пакеÑ:" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "ÐвеЎÑÑÑ ÑÐŒ'Ñ ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ³ÐŸ пакеÑа" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "ÐПÑÐžÐ»Ð°ÐœÐœÑ ÐŽÐŸÐŽÐ°ÐœÐŸ: " + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "ÐеÑÑÐ²Ð°ÐœÐœÑ Ð¿ÐŸÑОлаММÑЌО:" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "ЩП вО Ñ
ПÑеÑе вОЎалОÑО?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "вОЎалОÑО" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "пеÑезапÑÑÑОÑО" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " -пПпеÑеЎМÑй" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "" + diff --git a/locale/uk/LC_MESSAGES/setup.po b/locale/uk/LC_MESSAGES/setup.po new file mode 100644 index 000000000..5693044f1 --- /dev/null +++ b/locale/uk/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "ÐаÑкавП пÑПÑОЌП ЎП аÑОÑÑеМÑÑ ÑÑÑаМПвкО." + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "ÐваÑÑ ÑОÑÑÐµÐŒÑ Ð·Ð°Ñаз бÑЎе пеÑевÑÑеМП Ñ Ð·ÑÐŸÐ±Ð»ÐµÐœÐŸÐ±Ð°Ð·ÐŸÐ²Ñ ÑÑÑаМПвкО ÐŽÐ»Ñ ÑПгП, ÑПб запÑÑÑОÑО pyLoad." + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "ÐМаÑÐµÐœÐœÑ Ñ ÐºÐ²Ð°ÐŽÑаÑМОÑ
ÐŽÑжкаÑ
[] завжЎО Ñ Ð·ÐœÐ°ÑÐµÐœÐœÑ Ð·Ð° заЌПвÑаММÑÐŒ" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "ÐаÑОÑМÑÑÑ enter ÑПб пеÑезапÑÑÑÑÑÑ pyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "ÐÐŒ'Ñ ÐºÐŸÑОÑÑÑваÑа" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "ÐПва/Language" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "ÐÐŽÑеÑа" + +#: module/setup.py:313 +msgid "Port" +msgstr "ÐПÑÑ" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "СеÑвеÑ" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "# # SSL МалаÑÑÑÐ²Ð°ÐœÐœÑ # #" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "ÐОкПМаÑО ÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÐž з папкО pyLoad ÐŽÐ»Ñ ÑПгП ÑПб зÑПбОÑО ssl ÑеÑÑОÑÑкаÑО:" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "ЯкÑП вО вÑе зÑПбОлО, Ñ Ð²Ñе пÑПйÑлП ЎПбÑе, вО ЌПжеÑе акÑОвÑваÑО ssl заÑаз." + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "ÐкÑОвÑваÑО SSL?" + +#: module/setup.py:360 +msgid "Select action" +msgstr "ÐОбÑаÑО ÐŽÑÑ" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1 - СÑвПÑÐµÐœÐœÑ Ñа ÑеЎагÑÐ²Ð°ÐœÐœÑ ÐºÐŸÑОÑÑÑваÑ" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2 - СпОÑПк кПÑОÑÑÑваÑÑв" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3 - ÐОЎалОÑО кПÑОÑÑÑваÑа" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4 - ÐОÑ
ÑÐŽ" + +#: module/setup.py:376 +msgid "Users" +msgstr "ÐПÑОÑÑÑваÑÑ" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "ÐаÑОÑМÑÑÑ ÐºÐ»Ð°Ð²ÑÑÑ Enter, ÑПб закÑОÑО." + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "Ðе вЎалПÑÑ Ð·ÐŒÑМОÑО ÑлÑÑ
ЎП МалаÑÑÑваМÑ: %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "ÐаÑÐŸÐ»Ñ Ð·Ð°ÐœÐ°ÐŽÑП кПÑПÑкОй. ÐÑМÑЌалÑМа ЎПвжОМа 4 ÑОЌвПла." + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "ÐаÑÐŸÐ»Ñ (Ñе Ñаз): " + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "Так" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "ÐÑ" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "ÐевÑÑМОй ввÑÐŽ" + diff --git a/locale/vi/LC_MESSAGES/django.po b/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 000000000..6bdce3925 --- /dev/null +++ b/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Vietnamese\n" +"Language: vi_VN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "" + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "tắt" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "trên" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "" + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "Tên" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "Tình trạng" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "KÃch thưá»c" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "ÄÄng nháºp" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "Tên ngưá»i dùng" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "Máºt khẩu" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "Thư mục" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "" + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "Gá»i" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "Chung" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "Tà i khoản" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "Plugin" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "hợp lá»" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "Thêm" + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "" + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "" + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "" + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "" + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "" + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "Äiá»m Äến" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "" + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "Äóng" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "Há»§y bá»" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "" + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "khÃŽng giá»i hạn" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/vi/LC_MESSAGES/pyLoad.po b/locale/vi/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..90bf0609d --- /dev/null +++ b/locale/vi/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Vietnamese\n" +"Language: vi_VN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "" + +#: module/Core.py:340 +msgid "Starting" +msgstr "" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "" + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "" + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "" + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "khÃŽng giá»i hạn" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/vi/LC_MESSAGES/pyLoadCli.po b/locale/vi/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..0f79cabe8 --- /dev/null +++ b/locale/vi/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Vietnamese\n" +"Language: vi_VN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "Giao diá»n Dòng lá»nh" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "%s Tải xuá»ng:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "Tá»c Äá»:" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "KÃch thưá»c:" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "Kết thúc trong:" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "ID:" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "chá»:" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "Danh Mục:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "Thêm liên kết" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "(Un)Tạm dừng máy chá»§" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "Dừng máy chá»§" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "Thoát" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "" + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "Äang kiá»m tra %d liên kết:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "Táºp tin khÃŽng tá»n tại." + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "in trạng thái máy chá»§" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "in hà ng Äợi tải xuá»ng" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "Khá»i Äá»ng lại các táºp tin." + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "tạm dừng máy chá»§" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "tiếp tục tải xuá»ng" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "chuyá»n giữa tạm dừng/tiếp tục" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "dừng máy chá»§" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "Äá»a chá»:" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "Cá»ng:" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "Tên ngưá»i dùng:" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "Máºt khẩu:" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "Gói: %s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "Phân tÃch liên kết bạn muá»n thêm." + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "Nháºp %s khi xong." + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "Liên kết Äã thêm:" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "quay lại menu chÃnh" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "Quản lÜ liên kết" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr "- quay lại" + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "- kế tiếp" + diff --git a/locale/vi/LC_MESSAGES/setup.po b/locale/vi/LC_MESSAGES/setup.po new file mode 100644 index 000000000..a063269c2 --- /dev/null +++ b/locale/vi/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:39-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Vietnamese\n" +"Language: vi_VN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "" + +#: module/setup.py:53 +msgid "n" +msgstr "" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "Tên ngưá»i dùng" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "NgÃŽn ngữ" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "" + +#: module/setup.py:312 +msgid "Address" +msgstr "Äá»a chá»" + +#: module/setup.py:313 +msgid "Port" +msgstr "Cá»ng" + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "" + +#: module/setup.py:329 +msgid "Server" +msgstr "Máy chá»§" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "" + +#: module/setup.py:360 +msgid "Select action" +msgstr "" + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "" + +#: module/setup.py:376 +msgid "Users" +msgstr "" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "Máºt khẩu:" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "" + +#: module/setup.py:493 +msgid "yes" +msgstr "" + +#: module/setup.py:493 +msgid "true" +msgstr "" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "" + +#: module/setup.py:496 +msgid "false" +msgstr "" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "" + diff --git a/locale/zh/LC_MESSAGES/django.po b/locale/zh/LC_MESSAGES/django.po new file mode 100644 index 000000000..d34a347af --- /dev/null +++ b/locale/zh/LC_MESSAGES/django.po @@ -0,0 +1,684 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Chinese Traditional\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/webui/translations.js:1 +msgid "New Captcha Request" +msgstr "æ°éªè¯è¯·æ±" + +#: module/webui/translations.js:2 module/webui/themes/default/tml/captcha.html:7 +msgid "Please read the text on the captcha." +msgstr "请读åéªè¯ç äžçææ¬." + +#: module/webui/translations.js:3 +msgid "pyLoad restarted" +msgstr "pyLoadå·²ç»éå¯" + +#: module/webui/translations.js:4 +#: module/webui/themes/default/tml/settings_item.html:16 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "off" +msgstr "é" + +#: module/webui/translations.js:5 +msgid "Success" +msgstr "æå" + +#: module/webui/translations.js:6 +#: module/webui/themes/default/tml/settings_item.html:14 +#: module/webui/themes/default/tml/base.html:123 +#: module/webui/themes/default/tml/base.html:124 +msgid "on" +msgstr "é" + +#: module/webui/translations.js:7 +msgid "You are really sure you want to quit pyLoad?" +msgstr "确讀èŠéåºpyLoadåïŒ" + +#: module/webui/translations.js:8 +msgid "Restart Link" +msgstr "éŸæ¥éæ°åŒå§" + +#: module/webui/translations.js:9 +msgid "Delete Link" +msgstr "å é€éŸæ¥" + +#: module/webui/translations.js:10 +msgid "Please Enter a packagename." +msgstr "请èŸå
¥äžèœœå
åå" + +#: module/webui/translations.js:11 +msgid "Please click on the right captcha position." +msgstr "请ç¹å»æ£ç¡®çéªè¯ç äœçœ®" + +#: module/webui/translations.js:12 +msgid "Error occured." +msgstr "é误åçäº" + +#: module/webui/translations.js:13 +#: module/webui/themes/default/tml/filemanager.html:65 +#: module/webui/themes/default/tml/folder.html:14 +msgid "Folder is empty" +msgstr "æä»¶å€¹äžºç©º" + +#: module/webui/translations.js:14 +msgid "Failed" +msgstr "倱æ" + +#: module/webui/translations.js:15 +msgid "No Captchas to read." +msgstr "没æè·åéªè¯ç " + +#: module/webui/translations.js:16 +msgid "Passwords did not match." +msgstr "å¯ç äžç¬Š" + +#: module/webui/translations.js:17 +msgid "Settings saved." +msgstr "讟眮已ä¿å" + +#: module/webui/translations.js:18 +msgid "New folder" +msgstr "æ°æä»¶å€¹" + +#: module/webui/translations.js:19 +msgid "Are you sure you want to restart pyLoad?" +msgstr "ç¡®å®éå¯pyLoadåïŒ" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/webui/themes/default/tml/home.html:206 +msgid "Active Downloads" +msgstr "掻åšäžèœœ" + +#: module/webui/themes/default/tml/home.html:211 +#: module/webui/themes/default/tml/base.html:84 +msgid "Home" +msgstr "éŠé¡µ" + +#: module/webui/themes/default/tml/home.html:214 +#: module/webui/themes/default/tml/queue.html:15 +#: module/webui/themes/default/tml/window.html:34 +#: module/webui/themes/default/tml/base.html:87 +msgid "Queue" +msgstr "" + +#: module/webui/themes/default/tml/home.html:217 +#: module/webui/themes/default/tml/queue.html:17 +#: module/webui/themes/default/tml/window.html:36 +#: module/webui/themes/default/tml/base.html:90 +msgid "Collector" +msgstr "" + +#: module/webui/themes/default/tml/home.html:220 +#: module/webui/themes/default/tml/downloads.html:6 +#: module/webui/themes/default/tml/base.html:93 +msgid "Downloads" +msgstr "å·²äžèœœ" + +#: module/webui/themes/default/tml/home.html:226 +#: module/webui/themes/default/tml/logs.html:3 +#: module/webui/themes/default/tml/logs.html:4 +#: module/webui/themes/default/tml/base.html:99 +msgid "Logs" +msgstr "æ¥å¿" + +#: module/webui/themes/default/tml/home.html:229 +#: module/webui/themes/default/tml/settings.html:3 +#: module/webui/themes/default/tml/settings.html:4 +#: module/webui/themes/default/tml/base.html:102 +msgid "Config" +msgstr "é
眮" + +#: module/webui/themes/default/tml/home.html:237 +#: module/webui/themes/default/tml/queue.html:82 +#: module/webui/themes/default/tml/settings.html:91 +#: module/webui/themes/default/tml/window.html:7 +#: module/webui/themes/default/tml/admin.html:25 +msgid "Name" +msgstr "åçš±" + +#: module/webui/themes/default/tml/home.html:238 +#: module/webui/themes/default/tml/settings.html:93 +msgid "Status" +msgstr "çæ
" + +#: module/webui/themes/default/tml/home.html:239 +#: module/webui/themes/default/tml/info.html:14 +#: module/webui/themes/default/tml/info.html:15 +msgid "Information" +msgstr "ä¿¡æ¯" + +#: module/webui/themes/default/tml/home.html:240 +msgid "Size" +msgstr "倧å°" + +#: module/webui/themes/default/tml/home.html:241 +msgid "Progress" +msgstr "è¿åºŠ" + +#: module/webui/themes/default/tml/login.html:3 +#: module/webui/themes/default/tml/settings.html:178 +msgid "Login" +msgstr "ç»å
¥" + +#: module/webui/themes/default/tml/login.html:14 +msgid "Username" +msgstr "䜿çšè
åçš±" + +#: module/webui/themes/default/tml/login.html:19 +#: module/webui/themes/default/tml/queue.html:92 +#: module/webui/themes/default/tml/settings.html:92 +#: module/webui/themes/default/tml/settings.html:183 +#: module/webui/themes/default/tml/window.html:21 +msgid "Password" +msgstr "å¯ç¢Œ" + +#: module/webui/themes/default/tml/login.html:29 +msgid "Your username and password didn't match. Please try again." +msgstr "æšççšæ·ååå¯ç äžå¹é
, 请åè¯äžæ¬¡." + +#: module/webui/themes/default/tml/login.html:30 +msgid "To reset your login data or add an user run:" +msgstr "èŠé眮æšçç»åœæ°æ®ææ·»å äžäžªçšæ·, 请è¿è¡:" + +#: module/webui/themes/default/tml/queue.html:25 +msgid "Delete Finished" +msgstr "å é€å®æ" + +#: module/webui/themes/default/tml/queue.html:26 +msgid "Restart Failed" +msgstr "éå¯åºé" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Folder:" +msgstr "æä»¶å€¹:" + +#: module/webui/themes/default/tml/queue.html:65 +msgid "Password:" +msgstr "å¯ç :" + +#: module/webui/themes/default/tml/queue.html:79 +msgid "Edit Package" +msgstr "çŒèŸäžèœœ" + +#: module/webui/themes/default/tml/queue.html:80 +msgid "Edit the package detais below." +msgstr "ä¿®æ¹æä»¶å
è¯Šç»æ³šéä¿¡æ¯." + +#: module/webui/themes/default/tml/queue.html:83 +msgid "The name of the package." +msgstr "æä»¶å." + +#: module/webui/themes/default/tml/queue.html:87 +msgid "Folder" +msgstr "ç®é" + +#: module/webui/themes/default/tml/queue.html:88 +msgid "Name of subfolder for these downloads." +msgstr "æ€äžèœœçåç®åœå." + +#: module/webui/themes/default/tml/queue.html:93 +msgid "List of passwords used for unrar." +msgstr "UNRARè§£å猩å¯ç å衚." + +#: module/webui/themes/default/tml/queue.html:97 +#: module/webui/themes/default/tml/settings.html:167 +#: module/webui/themes/default/tml/captcha.html:33 +#: module/webui/themes/default/tml/admin.html:61 +#: module/webui/themes/default/tml/admin.html:91 +msgid "Submit" +msgstr "åæ" + +#: module/webui/themes/default/tml/queue.html:98 +#: module/webui/themes/default/tml/settings.html:198 +#: module/webui/themes/default/tml/window.html:41 +#: module/webui/themes/default/tml/admin.html:92 +msgid "Reset" +msgstr "é眮" + +#: module/webui/themes/default/tml/logout.html:8 +msgid "You were successfully logged out." +msgstr "æšå·²æå泚é." + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "Path" +msgstr "è·¯åŸ" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "absolute" +msgstr "ç»å¯¹" + +#: module/webui/themes/default/tml/pathchooser.html:39 +#: module/webui/themes/default/tml/pathchooser.html:41 +msgid "relative" +msgstr "çžå¯¹" + +#: module/webui/themes/default/tml/pathchooser.html:46 +msgid "name" +msgstr "åç§°" + +#: module/webui/themes/default/tml/pathchooser.html:47 +msgid "size" +msgstr "倧å°" + +#: module/webui/themes/default/tml/pathchooser.html:48 +msgid "type" +msgstr "ç±»å" + +#: module/webui/themes/default/tml/pathchooser.html:49 +msgid "last modified" +msgstr "æåä¿®æ¹" + +#: module/webui/themes/default/tml/pathchooser.html:54 +msgid "parent directory" +msgstr "ç¶ç®åœ" + +#: module/webui/themes/default/tml/pathchooser.html:70 +msgid "no content" +msgstr "没æå
容" + +#: module/webui/themes/default/tml/settings.html:16 +msgid "General" +msgstr "äžè¬èšå®" + +#: module/webui/themes/default/tml/settings.html:17 +msgid "Plugins" +msgstr "æä»¶" + +#: module/webui/themes/default/tml/settings.html:18 +msgid "Accounts" +msgstr "åž³æ¶" + +#: module/webui/themes/default/tml/settings.html:45 +#: module/webui/themes/default/tml/settings.html:74 +msgid "Choose a section from the menu" +msgstr "ä»èåäžéæ©äžé¡¹ç®" + +#: module/webui/themes/default/tml/settings.html:90 +msgid "Plugin" +msgstr "倿" + +#: module/webui/themes/default/tml/settings.html:94 +msgid "Premium" +msgstr "é«çº§åžå·" + +#: module/webui/themes/default/tml/settings.html:95 +msgid "Valid until" +msgstr "æææè³" + +#: module/webui/themes/default/tml/settings.html:96 +msgid "Traffic left" +msgstr "å©äœæµé" + +#: module/webui/themes/default/tml/settings.html:97 +msgid "Time" +msgstr "æ¶éŽ" + +#: module/webui/themes/default/tml/settings.html:98 +msgid "Max Parallel" +msgstr "æå€§è¿æ¥æ°" + +#: module/webui/themes/default/tml/settings.html:99 +msgid "Delete?" +msgstr "确讀å é€?" + +#: module/webui/themes/default/tml/settings.html:121 +msgid "valid" +msgstr "ææç" + +#: module/webui/themes/default/tml/settings.html:124 +msgid "not valid" +msgstr "æ æ" + +#: module/webui/themes/default/tml/settings.html:131 +msgid "yes" +msgstr "æ¯" + +#: module/webui/themes/default/tml/settings.html:134 +msgid "no" +msgstr "åŠ" + +#: module/webui/themes/default/tml/settings.html:168 +#: module/webui/themes/default/tml/settings.html:197 +#: module/webui/themes/default/tml/base.html:117 +msgid "Add" +msgstr "å¢å " + +#: module/webui/themes/default/tml/settings.html:176 +msgid "Add Account" +msgstr "æ°å¢åž³è" + +#: module/webui/themes/default/tml/settings.html:177 +msgid "Enter your account data to use premium features." +msgstr "èŸå
¥æšçåžæ·èµææ¥äœ¿çšé«çº§åèœ." + +#: module/webui/themes/default/tml/settings.html:179 +#: module/webui/themes/default/tml/admin.html:71 +msgid "Your username." +msgstr "æšççšæ·å." + +#: module/webui/themes/default/tml/settings.html:184 +#: module/webui/themes/default/tml/admin.html:76 +msgid "The password for this account." +msgstr "åœåå¯ç ä»
䞺æ€åžå·æçš." + +#: module/webui/themes/default/tml/settings.html:188 +msgid "Type" +msgstr "çš®é¡" + +#: module/webui/themes/default/tml/settings.html:189 +msgid "Choose the hoster for your account." +msgstr "è¯·éæ©æšåžå·å¯¹åºççœçç±»å." + +#: module/webui/themes/default/tml/logs.html:12 +#: module/webui/themes/default/tml/base.html:114 +msgid "Start" +msgstr "å¯åš" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "prev" +msgstr "äžäžé¡µ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "next" +msgstr "äžäžé¡µ" + +#: module/webui/themes/default/tml/logs.html:12 +msgid "End" +msgstr "宿" + +#: module/webui/themes/default/tml/info.html:18 +msgid "News" +msgstr "æ°é»" + +#: module/webui/themes/default/tml/info.html:21 +msgid "Support" +msgstr "ææ¯æ¯æ" + +#: module/webui/themes/default/tml/info.html:37 +msgid "System" +msgstr "系統" + +#: module/webui/themes/default/tml/info.html:40 +msgid "Python:" +msgstr "" + +#: module/webui/themes/default/tml/info.html:44 +msgid "OS:" +msgstr "æäœç³»ç»:" + +#: module/webui/themes/default/tml/info.html:48 +msgid "pyLoad version:" +msgstr "pyLoad çæ¬:" + +#: module/webui/themes/default/tml/info.html:52 +msgid "Installation Folder:" +msgstr "å®è£
æä»¶å€¹:" + +#: module/webui/themes/default/tml/info.html:56 +msgid "Config Folder:" +msgstr "é
眮æä»¶å€¹:" + +#: module/webui/themes/default/tml/info.html:60 +msgid "Download Folder:" +msgstr "äžèœœæä»¶å€¹:" + +#: module/webui/themes/default/tml/info.html:64 +msgid "Free Space:" +msgstr "空é²ç©ºéŽ:" + +#: module/webui/themes/default/tml/info.html:68 +msgid "Language:" +msgstr "è¯èš:" + +#: module/webui/themes/default/tml/info.html:72 +msgid "Webinterface Port:" +msgstr "Webçé¢ç«¯å£:" + +#: module/webui/themes/default/tml/info.html:76 +msgid "Remote Interface Port:" +msgstr "è¿çšæ¥å£ç«¯å£:" + +#: module/webui/themes/default/tml/setup.html:3 +#: module/webui/themes/default/tml/setup.html:4 +msgid "Setup" +msgstr "èšå®" + +#: module/webui/themes/default/tml/filemanager.html:19 +msgid "FileManager" +msgstr "æä»¶ç®¡çåš" + +#: module/webui/themes/default/tml/window.html:5 +#: module/webui/themes/default/tml/window.html:40 +msgid "Add Package" +msgstr "æ·»å äžèœœ" + +#: module/webui/themes/default/tml/window.html:6 +msgid "Paste your links or upload a container." +msgstr "ç²èŽŽéŸæ¥æè
äžäŒ äžå®¹åš." + +#: module/webui/themes/default/tml/window.html:8 +msgid "The name of the new package." +msgstr "æ°å»ºäžèœœçåå." + +#: module/webui/themes/default/tml/window.html:12 +msgid "Links" +msgstr "éŸæ¥" + +#: module/webui/themes/default/tml/window.html:13 +msgid "Paste your links here or any text and press the filter button." +msgstr "åšè¿éç²èŽŽæšçéŸæ¥æä»»äœææ¬å
容, ç¶åæ\"è¿æ»€\"æé®." + +#: module/webui/themes/default/tml/window.html:14 +msgid "Filter urls" +msgstr "è¿æ»€" + +#: module/webui/themes/default/tml/window.html:22 +msgid "Password for RAR-Archive" +msgstr "RARå猩å
å¯ç " + +#: module/webui/themes/default/tml/window.html:26 +msgid "File" +msgstr "æä»¶" + +#: module/webui/themes/default/tml/window.html:27 +msgid "Upload a container." +msgstr "äžäŒ äžå®¹åš." + +#: module/webui/themes/default/tml/window.html:31 +msgid "Destination" +msgstr "ç®çå°" + +#: module/webui/themes/default/tml/captcha.html:6 +msgid "Captcha reading" +msgstr "éªè¯ç 读åäž..." + +#: module/webui/themes/default/tml/captcha.html:13 +msgid "Captcha" +msgstr "éªè¯ç " + +#: module/webui/themes/default/tml/captcha.html:14 +msgid "The captcha." +msgstr "éªè¯ç ." + +#: module/webui/themes/default/tml/captcha.html:20 +msgid "Text" +msgstr "ææ¬" + +#: module/webui/themes/default/tml/captcha.html:21 +msgid "Input the text on the captcha." +msgstr "èŸå
¥éªè¯ç äžçææ¬." + +#: module/webui/themes/default/tml/captcha.html:34 +msgid "Close" +msgstr "éé" + +#: module/webui/themes/default/tml/base.html:20 +#: module/webui/themes/default/tml/base.html:139 +msgid "Webinterface" +msgstr "Webçé¢" + +#: module/webui/themes/default/tml/base.html:39 +msgid "pyLoad Update available!" +msgstr "pyLoad æŽæ°å¯çš!" + +#: module/webui/themes/default/tml/base.html:46 +msgid "Plugins updated, please restart!" +msgstr "æä»¶å·²æŽæ°, è¯·éæ°å¯åšçšåº!" + +#: module/webui/themes/default/tml/base.html:52 +msgid "Captcha waiting" +msgstr "éªè¯ç çåŸ
äž" + +#: module/webui/themes/default/tml/base.html:57 +msgid "Logout" +msgstr "泚é" + +#: module/webui/themes/default/tml/base.html:59 +#: module/webui/themes/default/tml/admin.html:8 +#: module/webui/themes/default/tml/admin.html:9 +msgid "Administrate" +msgstr "管ç" + +#: module/webui/themes/default/tml/base.html:61 +msgid "Info" +msgstr "ä¿¡æ¯" + +#: module/webui/themes/default/tml/base.html:65 +msgid "Please Login!" +msgstr "请ç»åœ!" + +#: module/webui/themes/default/tml/base.html:115 +msgid "Stop" +msgstr "忢" + +#: module/webui/themes/default/tml/base.html:116 +msgid "Cancel" +msgstr "åæ¶" + +#: module/webui/themes/default/tml/base.html:123 +msgid "Download:" +msgstr "äžèœœ:" + +#: module/webui/themes/default/tml/base.html:124 +msgid "Reconnect:" +msgstr "éæ°è¿æ¥:" + +#: module/webui/themes/default/tml/base.html:125 +msgid "Speed:" +msgstr "é床:" + +#: module/webui/themes/default/tml/base.html:126 +msgid "Active:" +msgstr "掻åš:" + +#: module/webui/themes/default/tml/base.html:127 +msgid "Reload page" +msgstr "å·æ°é¡µé¢" + +#: module/webui/themes/default/tml/base.html:157 +msgid "loading" +msgstr "å 蜜äž" + +#: module/webui/themes/default/tml/base.html:166 +msgid "Back to top" +msgstr "è¿åé¡¶éš" + +#: module/webui/themes/default/tml/admin.html:13 +msgid "Quit pyLoad" +msgstr "éåºpyLoad" + +#: module/webui/themes/default/tml/admin.html:14 +msgid "Restart pyLoad" +msgstr "éå¯pyLoad" + +#: module/webui/themes/default/tml/admin.html:18 +msgid "To add user or change passwords use:" +msgstr "æ·»å çšæ·ææŽæ¹å¯ç 请䜿çš:" + +#: module/webui/themes/default/tml/admin.html:19 +msgid "Important: Admin user have always all permissions!" +msgstr "éèŠæç€ºïŒç®¡çå莊æ·å
·ææææäœæéïŒ" + +#: module/webui/themes/default/tml/admin.html:28 +#: module/webui/themes/default/tml/admin.html:67 +msgid "Change Password" +msgstr "æŽæ¹å¯ç " + +#: module/webui/themes/default/tml/admin.html:31 +msgid "Admin" +msgstr "" + +#: module/webui/themes/default/tml/admin.html:34 +msgid "Permissions" +msgstr "讞å¯" + +#: module/webui/themes/default/tml/admin.html:41 +msgid "change" +msgstr "æŽæ¹" + +#: module/webui/themes/default/tml/admin.html:69 +msgid "Enter your current and desired Password." +msgstr "请èŸå
¥æšåœå以åéèŠä¿®æ¹çå¯ç ." + +#: module/webui/themes/default/tml/admin.html:70 +msgid "User" +msgstr "çšæ·" + +#: module/webui/themes/default/tml/admin.html:75 +msgid "Current password" +msgstr "åœåå¯ç " + +#: module/webui/themes/default/tml/admin.html:80 +msgid "New password" +msgstr "æ°å¯ç " + +#: module/webui/themes/default/tml/admin.html:81 +msgid "The new password." +msgstr "æ°çå¯ç ." + +#: module/webui/themes/default/tml/admin.html:85 +msgid "New password (repeat)" +msgstr "æ°å¯ç (éå€)" + +#: module/webui/themes/default/tml/admin.html:86 +msgid "Please repeat the new password." +msgstr "请确讀æšçæ°å¯ç ." + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ç¡éå¶" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + diff --git a/locale/zh/LC_MESSAGES/pyLoad.po b/locale/zh/LC_MESSAGES/pyLoad.po new file mode 100644 index 000000000..19a8a1487 --- /dev/null +++ b/locale/zh/LC_MESSAGES/pyLoad.po @@ -0,0 +1,865 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Chinese Traditional\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/Core.py:182 +msgid "Received Quit signal" +msgstr "æ¶å°éåºèšè" + +#: module/Core.py:303 +#, python-format +msgid "pyLoad already running with pid %s" +msgstr "pyLoadå·²ç¶åšå·è¡ïŒpid %s" + +#: module/Core.py:317 +#, python-format +msgid "Failed changing group: %s" +msgstr "ç¡æ³æ¹è®çŸ€çµïŒ %s" + +#: module/Core.py:327 +#, python-format +msgid "Failed changing user: %s" +msgstr "ç¡æ³æ¹è®äœ¿çšè
ïŒ %s" + +#: module/Core.py:329 +msgid "folder for logs" +msgstr "LOGæä»¶å€¹" + +#: module/Core.py:340 +msgid "Starting" +msgstr "éå§" + +#: module/Core.py:341 +#, python-format +msgid "Using home directory: %s" +msgstr "䜿çšå®¶ç®éïŒ %s" + +#: module/Core.py:350 +msgid "pycrypto to decode container files" +msgstr "䜿çšpycryptoè§£å¯æä»¶" + +#: module/Core.py:353 +msgid "folder for temporary files" +msgstr "äžŽæ¶æä»¶å€¹" + +#: module/Core.py:358 +msgid "folder for downloads" +msgstr "äžèœœæä»¶å€¹" + +#: module/Core.py:361 +msgid "OpenSSL for secure connection" +msgstr "䜿çšOpenSSLå®å
šç»é" + +#: module/Core.py:365 +msgid "Moving old user config to DB" +msgstr "å°æ§çšæ·è®Ÿå®ç§»å
¥æ°æ®åº" + +#: module/Core.py:368 +msgid "Please check your logindata with ./pyload.py -u" +msgstr "请æ§è¡./pyload.py -u æ¥ç¡®è®€äœ çlogindata" + +#: module/Core.py:371 +msgid "All links removed" +msgstr "åªé€ææé£çµ" + +#: module/Core.py:402 +#, python-format +msgid "Downloadtime: %s" +msgstr "äžèœœæ¶éŽïŒ%s" + +#: module/Core.py:412 +#, python-format +msgid "Free space: %s" +msgstr "å©é€ç©ºéïŒ %s" + +#: module/Core.py:432 +msgid "Activating Accounts..." +msgstr "åååž³æ¶..." + +#: module/Core.py:438 +msgid "Activating Plugins..." +msgstr "æ¿æŽ»æä»¶äž..." + +#: module/Core.py:441 +msgid "pyLoad is up and running" +msgstr "pyLoadå·²æ¯ææ°ççæ
" + +#: module/Core.py:460 +msgid "restarting pyLoad" +msgstr "éæ°ååpyLoad" + +#: module/Core.py:464 +msgid "pyLoad quits" +msgstr "é¢épyLoad" + +#: module/Core.py:521 +#, python-format +msgid "Install %s" +msgstr "å®è£
%s" + +#: module/Core.py:557 +#, python-format +msgid "could not find %(desc)s: %(name)s" +msgstr "æ æ³æŸå°%(desc)s: %(name)s" + +#: module/Core.py:559 +#, python-format +msgid "could not create %(desc)s: %(name)s" +msgstr "æ æ³å建%(desc)s: %(name)s" + +#: module/Core.py:580 +msgid "shutting down..." +msgstr "éé..." + +#: module/Core.py:597 +msgid "error while shutting down" +msgstr "ééæåºçŸé¯èª€" + +#: module/Core.py:661 +msgid "killed pyLoad from Terminal" +msgstr "" + +#: module/database/DatabaseBackend.py:174 +msgid "Filedatabase was deleted due to incompatible version." +msgstr "" + +#: module/database/DatabaseBackend.py:189 +msgid "Filedatabase could NOT be converted." +msgstr "" + +#: module/database/DatabaseBackend.py:198 +msgid "Database was converted from v2 to v3." +msgstr "" + +#: module/database/DatabaseBackend.py:206 +msgid "Database was converted from v3 to v4." +msgstr "" + +#: module/database/DatabaseBackend.py:252 +msgid "Converting old Django DB" +msgstr "" + +#: module/database/FileDatabase.py:45 +msgid "finished" +msgstr "已宿" + +#: module/database/FileDatabase.py:45 +msgid "offline" +msgstr "é¢ç·" + +#: module/database/FileDatabase.py:45 +msgid "online" +msgstr "ç·äž" + +#: module/database/FileDatabase.py:45 +msgid "queued" +msgstr "äœå" + +#: module/database/FileDatabase.py:45 +msgid "skipped" +msgstr "è·³é" + +#: module/database/FileDatabase.py:45 +msgid "waiting" +msgstr "çåŸ
äž" + +#: module/database/FileDatabase.py:45 +msgid "temp. offline" +msgstr "æ«æé¢ç·" + +#: module/database/FileDatabase.py:45 +msgid "starting" +msgstr "éå§" + +#: module/database/FileDatabase.py:45 +msgid "failed" +msgstr "倱æ" + +#: module/database/FileDatabase.py:45 +msgid "aborted" +msgstr "äžæ¢" + +#: module/database/FileDatabase.py:45 +msgid "decrypting" +msgstr "è§£æ" + +#: module/database/FileDatabase.py:45 +msgid "custom" +msgstr "èªèš" + +#: module/database/FileDatabase.py:45 +msgid "downloading" +msgstr "äžèŒäž" + +#: module/database/FileDatabase.py:45 +msgid "processing" +msgstr "èçäž" + +#: module/database/FileDatabase.py:45 +msgid "unknown" +msgstr "æªç¥" + +#: module/database/FileDatabase.py:531 module/plugins/hooks/IRCInterface.py:74 +#: module/plugins/hooks/XMPPInterface.py:83 +#, python-format +msgid "Package finished: %s" +msgstr "å¥ä»¶å·²å®æïŒ %s" + +#: module/remote/ThriftBackend.py:39 +msgid "Using SSL ThriftBackend" +msgstr "" + +#: module/remote/RemoteManager.py:35 +#, python-format +msgid "Remote backend error: %s" +msgstr "é 端é¯èª€ïŒ %s" + +#: module/remote/RemoteManager.py:82 +#, python-format +msgid "Starting %(name)s: %(addr)s:%(port)s" +msgstr "%(name)s ïŒ%(addr)s:%(port)s ååäž" + +#: module/remote/RemoteManager.py:84 +#, python-format +msgid "Failed loading backend %(name)s | %(error)s" +msgstr "ç¡æ³èŒå
¥ %(name)sïŒ %(error)s" + +#: module/webui/app/json.py:57 +#, python-format +msgid "waiting %s" +msgstr "" + +#: module/threads/ServerThread.py:35 +msgid "SSL certificates not found." +msgstr "æ²ææŸå°SSLæè" + +#: module/threads/ServerThread.py:39 +#, python-format +msgid "Sorry, we dropped support for starting %s directly within pyLoad" +msgstr "" + +#: module/threads/ServerThread.py:40 +msgid "You can use the threaded server which offers good performance and ssl," +msgstr "" + +#: module/threads/ServerThread.py:41 +#, python-format +msgid "of course you can still use your existing %s with pyLoads fastcgi server" +msgstr "" + +#: module/threads/ServerThread.py:42 +msgid "sample configs are located in the module/webui/servers directory" +msgstr "" + +#: module/threads/ServerThread.py:49 +#, python-format +msgid "Can't use %(server)s, python-flup is not installed!" +msgstr "" + +#: module/threads/ServerThread.py:56 +#, python-format +msgid "Error importing lightweight server: %s" +msgstr "" + +#: module/threads/ServerThread.py:57 +msgid "You need to download and compile bjoern, https://github.com/jonashaag/bjoern" +msgstr "" + +#: module/threads/ServerThread.py:58 +msgid "Copy the boern.so to module/lib folder or use setup.py install" +msgstr "" + +#: module/threads/ServerThread.py:59 +msgid "Of course you need to be familiar with linux and know how to compile software" +msgstr "" + +#: module/threads/ServerThread.py:63 +msgid "Server set to threaded, due to known performance problems on windows." +msgstr "" + +#: module/threads/ServerThread.py:80 module/threads/ServerThread.py:103 +msgid "This server offers no SSL, please consider using threaded instead" +msgstr "ç®åçæååšäžæ¯æŽSSLïŒè«å°äŒºæåšæš¡åŒæ¹çºThreaded" + +#: module/threads/ServerThread.py:82 +#, python-format +msgid "Starting builtin webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:87 +#, python-format +msgid "Starting threaded SSL webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:91 +#, python-format +msgid "Starting threaded webserver: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:97 +#, python-format +msgid "Starting fastcgi server: %(host)s:%(port)d" +msgstr "" + +#: module/threads/ServerThread.py:105 +#, python-format +msgid "Starting lightweight webserver (bjoern): %(host)s:%(port)d" +msgstr "" + +#: module/webui/app/pyload.py:125 +msgid "You dont have permission to access this page." +msgstr "" + +#: module/webui/app/pyload.py:193 +msgid "Download directory not found." +msgstr "" + +#: module/webui/app/pyload.py:260 module/webui/app/pyload.py:267 +msgid "unlimited" +msgstr "ç¡éå¶" + +#: module/webui/app/pyload.py:262 module/webui/app/pyload.py:269 +msgid "not available" +msgstr "" + +#: module/webui/app/pyload.py:508 +msgid "Run pyload.py -s to access the setup." +msgstr "" + +#: module/network/HTTPDownload.py:245 +#, python-format +msgid "Download chunks failed, fallback to single connection | %s" +msgstr "ååäžèŒå€±æïŒæ¡çšå®äžé£æ¥äžèŒïœ%s" + +#: module/threads/PluginThread.py:183 +#, python-format +msgid "Download starts: %s" +msgstr "éå§äžèŒ %s" + +#: module/threads/PluginThread.py:189 +#, python-format +msgid "Download finished: %s" +msgstr "%s äžèŒå®æ" + +#: module/threads/PluginThread.py:194 module/threads/PluginThread.py:365 +#, python-format +msgid "Plugin %s is missing a function." +msgstr "%s æš¡çµçŒºå°çžéåèœ" + +#: module/threads/PluginThread.py:202 module/threads/PluginThread.py:265 +#: module/threads/PluginThread.py:382 +#, python-format +msgid "Download aborted: %s" +msgstr "åæ¶äžèŒ %s" + +#: module/threads/PluginThread.py:222 +#, python-format +msgid "Download restarted: %(name)s | %(msg)s" +msgstr "éæ°äžèŒ%(name)s ïœ%(msg)s" + +#: module/threads/PluginThread.py:231 module/threads/PluginThread.py:373 +#, python-format +msgid "Download is offline: %s" +msgstr "äžèŒä»»åæ·ç·ïŒ%s" + +#: module/threads/PluginThread.py:234 +#, python-format +msgid "Download is temporary offline: %s" +msgstr "äžèŒä»»åæ«ææ·ç·ïŒ%s" + +#: module/threads/PluginThread.py:237 module/threads/PluginThread.py:304 +#, python-format +msgid "Download failed: %(name)s | %(msg)s" +msgstr "%(name)s äžèŒå€±æïœ%(msg)s" + +#: module/threads/PluginThread.py:254 +msgid "Couldn't connect to host or connection reset, waiting 1 minute and retry." +msgstr "ç¡æ³é£ç·è³hostïŒäžåéåŸé詊" + +#: module/threads/PluginThread.py:290 +#, python-format +msgid "Download skipped: %(name)s due to %(plugin)s" +msgstr "%(name)s åæ¶äžèŒïŒç±æŒ %(plugin)s" + +#: module/threads/PluginThread.py:361 +#, python-format +msgid "Decrypting starts: %s" +msgstr "" + +#: module/threads/PluginThread.py:376 module/threads/PluginThread.py:394 +#, python-format +msgid "Decrypting failed: %(name)s | %(msg)s" +msgstr "" + +#: module/threads/PluginThread.py:388 +#, python-format +msgid "Retrying %s" +msgstr "" + +#: module/threads/PluginThread.py:635 +#, python-format +msgid "Info Fetching for %(name)s failed | %(err)s" +msgstr "ååŸ %(name)sçé¯èª€è³èš|%(err)s" + +#: module/HookManager.py:90 module/plugins/Hook.py:102 +#, python-format +msgid "Error executing hooks: %s" +msgstr "" + +#: module/HookManager.py:140 +#, python-format +msgid "Failed activating %(name)s" +msgstr "åçš %(name)s æçŒçé¯èª€" + +#: module/HookManager.py:144 +#, python-format +msgid "Activated plugins: %s" +msgstr "" + +#: module/HookManager.py:145 +#, python-format +msgid "Deactivate plugins: %s" +msgstr "" + +#: module/ThreadManager.py:137 +#, python-format +msgid "Reconnect Failed: %s" +msgstr "鿰飿¥å€±æ: %s" + +#: module/ThreadManager.py:176 +msgid "Reconnect script not found!" +msgstr "鿰飿¥è
³æ¬æªæŸå° ïŒ" + +#: module/ThreadManager.py:182 +msgid "Starting reconnect" +msgstr "éå§é詊" + +#: module/ThreadManager.py:196 +msgid "Failed executing reconnect script!" +msgstr "å·è¡é詊è
³æ¬å€±æ" + +#: module/ThreadManager.py:208 +#, python-format +msgid "Reconnected, new IP: %s" +msgstr "äœ¿çšæ°IP: %s é詊" + +#: module/ThreadManager.py:288 +msgid "Not enough space left on device" +msgstr "å²å空éäžè¶³" + +#: module/plugins/Account.py:85 module/plugins/Account.py:91 +#, python-format +msgid "Could not login with account %(user)s | %(msg)s" +msgstr "ç¡æ³ç»å
¥%(user)s ïœ%(msg)s" + +#: module/plugins/Account.py:86 +msgid "Wrong Password" +msgstr "å¯ç¢Œé¯èª€" + +#: module/plugins/Account.py:240 +#, python-format +msgid "Your Time %s has wrong format, use: 1:22-3:44" +msgstr "" + +#: module/plugins/Account.py:266 +#, python-format +msgid "Account %s has not enough traffic, checking again in 30min" +msgstr "åž³æ¶ %s æµéçšé¿ïŒ30åéåŸéæ°æª¢æ¥" + +#: module/plugins/Account.py:273 +#, python-format +msgid "Account %s is expired, checking again in 1h" +msgstr "åž³æ¶ %s å·²éæïŒäžå°æåŸé詊" + +#: module/plugins/crypter/SerienjunkiesOrg.py:128 +msgid "Downloadlimit reached" +msgstr "å·²éå°äžèŒæµéäžé" + +#: module/plugins/PluginManager.py:153 +#, python-format +msgid "%s has a invalid pattern." +msgstr "" + +#: module/plugins/PluginManager.py:272 +#, python-format +msgid "Error importing %(name)s: %(msg)s" +msgstr "çŒçŸé¯èª€ %(name)s: %(msg)s" + +#: module/plugins/internal/MultiHoster.py:133 +msgid "No Hoster loaded" +msgstr "æŸäžå°ä»»äœHoster" + +#: module/plugins/accounts/BitshareCom.py:37 +msgid "Activate direct Download in your Bitshare Account" +msgstr "åŸæšçBitshareåž³èäžçŽæ¥äžèŒ" + +#: module/plugins/container/LinkList.py:65 +msgid "LinkList could not be cleared." +msgstr "" + +#: module/plugins/AccountManager.py:88 +msgid "Account settings deleted, due to new config format." +msgstr "" + +#: module/plugins/hoster/BasePlugin.py:65 +msgid "Authorization required (username:password)" +msgstr "éèŠèªèïŒåž³èïŒå¯ç¢ŒïŒ" + +#: module/plugins/hoster/SimplydebridCom.py:25 +#: module/plugins/hoster/RealdebridCom.py:41 +#: module/plugins/hoster/FreeWayMe.py:38 module/plugins/hoster/ZeveraCom.py:22 +#: module/plugins/hoster/UnrestrictLi.py:53 +#: module/plugins/hoster/Premium4Me.py:28 module/plugins/hoster/FastixRu.py:36 +#: module/plugins/hoster/AlldebridCom.py:38 +#: module/plugins/hoster/DebridItaliaCom.py:40 +#: module/plugins/hoster/RPNetBiz.py:26 +#: module/plugins/hoster/MultiDebridCom.py:41 +#: module/plugins/hoster/ReloadCc.py:24 module/plugins/hoster/RehostTo.py:26 +#: module/plugins/hoster/PremiumizeMe.py:22 +#: module/plugins/hooks/RPNetBiz.py:43 +#, python-format +msgid "Please enter your %s account or deactivate this plugin" +msgstr "è«èŒžå
¥äœ çåž³æ¶ææ¯åçšæ€æš¡çµ" + +#: module/plugins/hoster/FilesMailRu.py:99 +#, python-format +msgid "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." +msgstr "äžèŒæªæ¡äžå
å«HTMLèªæ³ïŒè§£æé¯èª€åïŒæºåé詊" + +#: module/plugins/hoster/NetloadIn.py:146 +#: module/plugins/hoster/NetloadIn.py:170 +msgid "File temporarily not available" +msgstr "æªæ¡æ«æç¡æ³äžèŒ" + +#: module/plugins/hoster/NetloadIn.py:183 +#, python-format +msgid "Netload: waiting between downloads %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:214 +#, python-format +msgid "Netload: waiting for captcha %d s." +msgstr "" + +#: module/plugins/hoster/NetloadIn.py:252 +msgid "Downloaded File was empty" +msgstr "äžèŒçæªæ¡æ¯ç©ºç" + +#: module/plugins/hoster/UploadedTo.py:129 +msgid "API key invalid" +msgstr "APIéé°ç¡æ" + +#: module/plugins/hoster/UploadedTo.py:153 +#, python-format +msgid "%s: Not enough traffic left" +msgstr "%s: æµéå·²çšå®" + +#: module/plugins/hoster/UploadedTo.py:156 +msgid "Traffic exceeded" +msgstr "è¶
åºæµééå¶" + +#: module/plugins/hoster/RapidshareCom.py:100 +msgid "Rapidshare: Traffic Share (direct download)" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:127 +#: module/plugins/hoster/RapidshareCom.py:194 +msgid "Already downloading from this ip address, waiting 60 seconds" +msgstr "æ€IPäœåå·²åšäžèŒåŠäžé
ç®ïŒè«çåŸ
å
åç§åŸé詊" + +#: module/plugins/hoster/RapidshareCom.py:131 +msgid "Invalid Auth Code, download will be restarted" +msgstr "é©è倱æïŒä»»åå³å°é詊" + +#: module/plugins/hoster/RapidshareCom.py:199 +msgid "RapidShareCom: No free slots" +msgstr "" + +#: module/plugins/hoster/RapidshareCom.py:202 +msgid "You need a premium account for this file" +msgstr "æ€æªæ¡éèŠé«çŽçšæ¶æèœäžèŒ" + +#: module/plugins/hoster/RapidshareCom.py:204 +msgid "Filename reported invalid" +msgstr "äžæ£ç¢ºçæªå" + +#: module/plugins/hoster/FileserveCom.py:99 +msgid "Parallel download error, now waiting 60s." +msgstr "åæäžèŒé¯èª€ïŒ60ç§åŸé詊" + +#: module/plugins/hoster/FileserveCom.py:215 +msgid "Not logged in." +msgstr "æªç»å
¥" + +#: module/plugins/hoster/MegaNz.py:56 +msgid "Decryption failed" +msgstr "è§£æå€±æ" + +#: module/plugins/hoster/MegaNz.py:106 +msgid "No file key provided in the URL" +msgstr "URLæªæäŸéé°" + +#: module/plugins/hoster/MegaNz.py:118 +msgid "Error code:" +msgstr "é¯èª€ç¢ŒïŒ" + +#: module/plugins/Container.py:68 +msgid "File not exists." +msgstr "" + +#: module/plugins/hooks/UpdateManager.py:74 +msgid "*** Plugins have been updated, please restart pyLoad ***" +msgstr "ïŒïŒïŒå€æå·²æŽæ°ïŒè«éæ°ååpyLoadïŒïŒïŒ" + +#: module/plugins/hooks/UpdateManager.py:76 +msgid "Plugins updated and reloaded" +msgstr "å€æå·²æŽæ°" + +#: module/plugins/hooks/UpdateManager.py:79 +msgid "No plugin updates available" +msgstr "å€ææ²æå¯çšçæŽæ°" + +#: module/plugins/hooks/UpdateManager.py:96 +msgid "No Updates for pyLoad" +msgstr "pyLoadæ²æå¯çšçæŽæ°" + +#: module/plugins/hooks/UpdateManager.py:100 +#, python-format +msgid "*** New pyLoad Version %s available ***" +msgstr "ïŒïŒïŒpyLoadææ°çæ¬%så¯äœ¿çšïŒïŒïŒ" + +#: module/plugins/hooks/UpdateManager.py:101 +msgid "*** Get it here: http://pyload.org/download ***" +msgstr "*** è«åŸæ€äžèŒ http://pyload.org/download ***" + +#: module/plugins/hooks/UpdateManager.py:104 +msgid "Not able to connect server for updates" +msgstr "ç¡æ³é£ç·è³æŽæ°äŒºæåš" + +#: module/plugins/hooks/UpdateManager.py:148 +#, python-format +msgid "New version of %(type)s|%(name)s : %(version).2f" +msgstr "æ°çæ¬ %(type)s|%(name)s : %(version).2f" + +#: module/plugins/hooks/UpdateManager.py:157 +#: module/plugins/hooks/UpdateManager.py:162 +#, python-format +msgid "Error when updating %s" +msgstr "æŽæ° %s æçŒçé¯èª€" + +#: module/plugins/hooks/UpdateManager.py:162 +msgid "Version mismatch" +msgstr "çæ¬äžå" + +#: module/plugins/hooks/IRCInterface.py:82 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s " +msgstr "%(name)s @ %(plugin)s 已宿" + +#: module/plugins/hooks/IRCInterface.py:95 +#, python-format +msgid "New Captcha Request: %s" +msgstr "é©èç¢Œè«æ±: %s" + +#: module/plugins/hooks/IRCInterface.py:96 +#, python-format +msgid "Answer with 'c %s text on the captcha'" +msgstr "è«èŒžå
¥é©è碌äžçæå %s" + +#: module/plugins/hooks/Premium4Me.py:29 +msgid "Please add your premium.to account first and restart pyLoad" +msgstr "è«å
æ·»å premium.toåž³æ¶äžŠéæ°ååpyLoad" + +#: module/plugins/hooks/HotFolder.py:82 +#, python-format +msgid "Added %s from HotFolder" +msgstr "åŸHotFolderå¢å %s" + +#: module/plugins/hooks/ExtractArchive.py:95 +#, python-format +msgid "No %s installed" +msgstr "æªå®è£ %s" + +#: module/plugins/hooks/ExtractArchive.py:97 +#: module/plugins/hooks/ExtractArchive.py:102 +#, python-format +msgid "Could not activate %s" +msgstr "ç¡æ³åçš %s" + +#: module/plugins/hooks/ExtractArchive.py:107 +msgid "Activated" +msgstr "å·²åçš" + +#: module/plugins/hooks/ExtractArchive.py:109 +msgid "No Extract plugins activated" +msgstr "è§£å£çž®å€ææªåçš" + +#: module/plugins/hooks/ExtractArchive.py:121 +#, python-format +msgid "Package %s queued for later extracting" +msgstr "ä»»å %s å·²æå
¥è§£å£äœå" + +#: module/plugins/hooks/ExtractArchive.py:144 +#, python-format +msgid "Check package %s" +msgstr "檢æ¥äžèŒä»»å %s" + +#: module/plugins/hooks/ExtractArchive.py:185 +#, python-format +msgid "Extract to %s" +msgstr "è§£å£çž®è³ %s" + +#: module/plugins/hooks/ExtractArchive.py:200 +msgid "No files found to extract" +msgstr "ç¡æ³æŸå°å£çž®æª" + +#: module/plugins/hooks/ExtractArchive.py:207 +msgid "extracting" +msgstr "è§£å£çž®äž" + +#: module/plugins/hooks/ExtractArchive.py:218 +msgid "Password protected" +msgstr "被å å¯çå£çž®æª" + +#: module/plugins/hooks/ExtractArchive.py:239 +msgid "Wrong password" +msgstr "å¯ç¢Œé¯èª€" + +#: module/plugins/hooks/ExtractArchive.py:247 +#, python-format +msgid "Deleting %s files" +msgstr "åªé€æªæ¡ %s" + +#: module/plugins/hooks/ExtractArchive.py:254 +msgid "Extracting finished" +msgstr "è§£å£çž®å®æ" + +#: module/plugins/hooks/ExtractArchive.py:260 +msgid "Archive Error" +msgstr "å£çž®æªææ¯" + +#: module/plugins/hooks/ExtractArchive.py:262 +msgid "CRC Mismatch" +msgstr "CRCäžæ£ç¢º" + +#: module/plugins/hooks/ExtractArchive.py:266 +msgid "Unknown Error" +msgstr "æªç¥é¯èª€" + +#: module/plugins/hooks/ExtractArchive.py:318 +msgid "Setting User and Group failed" +msgstr "èšå®äœ¿çšè
å矀çµå€±æ" + +#: module/plugins/hooks/ClickAndLoad.py:75 +msgid "Click'N'Load: Port 9666 already in use" +msgstr "Click'N'Load: 9666é已被䜿çš" + +#: module/plugins/hooks/CaptchaTrader.py:69 +#: module/plugins/hooks/Captcha9kw.py:59 +#: module/plugins/hooks/ExpertDecoders.py:50 +#, python-format +msgid "%s credits left" +msgstr "é¡åºŠå©é€ %s" + +#: module/plugins/hooks/CaptchaTrader.py:117 +msgid "Could not send response." +msgstr "ç¡æ³çŒéåæã" + +#: module/plugins/hooks/CaptchaTrader.py:135 +msgid "Your CaptchaTrader Account has not enough credits" +msgstr "CaptchaTraderåž³æ¶é¡åºŠäžè¶³" + +#: module/plugins/hooks/LinkdecrypterCom.py:43 +msgid "Crypter list not found" +msgstr "æªæŸå°Crypteræž
å®" + +#: module/plugins/hooks/LinkdecrypterCom.py:57 +msgid "Crypter list is empty" +msgstr "Crypteræž
宿¯ç©ºç" + +#: module/plugins/hooks/XMPPInterface.py:91 +#, python-format +msgid "Download finished: %(name)s @ %(plugin)s" +msgstr "%(name)s @ %(plugin)s 宿" + +#: module/plugins/hooks/Captcha9kw.py:93 +#, python-format +msgid "New CaptchaID from upload: %s : %s" +msgstr "äžå³æ°çCaptchaIDïŒ%s:%s" + +#: module/plugins/hooks/Captcha9kw.py:129 +msgid "Your Captcha 9kw.eu Account has not enough credits" +msgstr "9kw.euåž³æ¶é¡åºŠäžè¶³" + +#: module/plugins/hooks/ExternalScripts.py:54 +#, python-format +msgid "Installed scripts for %s: " +msgstr "%s å·²å®è£çè
³æ¬" + +#: module/plugins/hooks/ExternalScripts.py:69 +msgid "Script not executable:" +msgstr "ç¡æ³å·è¡è
³æ¬" + +#: module/plugins/hooks/ExternalScripts.py:80 +#, python-format +msgid "Error in %(script)s: %(error)s" +msgstr "%(script)sïŒ %(error)s" + +#: module/plugins/hooks/ExpertDecoders.py:95 +msgid "Your ExpertDecoders Account has not enough credits" +msgstr "ExpertDecodersåž³æ¶é¡åºŠäžè¶³" + +#: module/plugins/hooks/RehostTo.py:32 +msgid "Please add your rehost.to account first and restart pyLoad" +msgstr "è«å
æ·»å rehost.toåž³æ¶äžŠéæ°ååpyLoad" + +#: module/plugins/hooks/PremiumizeMe.py:48 +msgid "Please add a valid premiumize.me account first and restart pyLoad." +msgstr "è«å
èšå®premiumize.meåž³æ¶äžŠéæ°ååpyLoad" + +#: module/plugins/hooks/CaptchaBrotherhood.py:69 +#, python-format +msgid "%d credits left" +msgstr "é¡åºŠå©äž %d" + +#: module/plugins/Plugin.py:389 +msgid "Pil and tesseract not installed and no Client connected for captcha decrypting" +msgstr "å°æªå®è£PilåtesseractïŒå°æªé£æ¥è³éèŠè§£æç客æ¶ç«¯" + +#: module/plugins/Plugin.py:393 +msgid "No captcha result obtained in appropiate time by any of the plugins." +msgstr "" + +#: module/plugins/Plugin.py:498 module/plugins/Plugin.py:532 +#, python-format +msgid "Setting User and Group failed: %s" +msgstr "èšçœ®äœ¿çšè
åçµå€±æïŒ %s" + +#: module/CaptchaManager.py:78 +msgid "No Client connected for captcha decrypting" +msgstr "" + +#: module/Api.py:330 +#, python-format +msgid "Added package %(name)s containing %(count)d links" +msgstr "" + +#: module/Api.py:593 +#, python-format +msgid "Added %(count)d links to package #%(package)d " +msgstr "" + +#: module/common/JsEngine.py:156 +msgid "No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + diff --git a/locale/zh/LC_MESSAGES/pyLoadCli.po b/locale/zh/LC_MESSAGES/pyLoadCli.po new file mode 100644 index 000000000..47d8acb01 --- /dev/null +++ b/locale/zh/LC_MESSAGES/pyLoadCli.po @@ -0,0 +1,295 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Chinese Traditional\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/cli/Cli.py:75 module/cli/Cli.py:133 +msgid " Command Line Interface" +msgstr "åœä»€åä»é¢" + +#: module/cli/Cli.py:165 +#, python-format +msgid "%s Downloads:" +msgstr "å·²äžèŒ %s:" + +#: module/cli/Cli.py:177 +msgid " Speed: " +msgstr "é床:" + +#: module/cli/Cli.py:177 +msgid " Size: " +msgstr "倧å°:" + +#: module/cli/Cli.py:178 +msgid " Finished in: " +msgstr "è·é¢å®æ:" + +#: module/cli/Cli.py:179 +msgid " ID: " +msgstr "ç·šè:" + +#: module/cli/Cli.py:184 +msgid "waiting: " +msgstr "çåŸ
äž:" + +#: module/cli/Cli.py:191 module/cli/Cli.py:193 +msgid "Status:" +msgstr "çæ
:" + +#: module/cli/Cli.py:191 +msgid "paused" +msgstr "å·²æ«å" + +#: module/cli/Cli.py:193 +msgid "running" +msgstr "å·è¡äž" + +#: module/cli/Cli.py:196 +msgid "total Speed" +msgstr "çžœé床" + +#: module/cli/Cli.py:196 +msgid "Files in queue" +msgstr "äœåäžæªæ¡" + +#: module/cli/Cli.py:197 +msgid "Total" +msgstr "çžœèš" + +#: module/cli/Cli.py:203 +msgid "Menu:" +msgstr "衚å®:" + +#: module/cli/Cli.py:205 +msgid " Add Links" +msgstr "å å
¥é£çµ" + +#: module/cli/Cli.py:206 +msgid " Manage Queue" +msgstr "äœå管ç" + +#: module/cli/Cli.py:207 +msgid " Manage Collector" +msgstr "æ¶éåšç®¡ç" + +#: module/cli/Cli.py:208 +msgid " (Un)Pause Server" +msgstr "æ«å/åå 䌺æåš" + +#: module/cli/Cli.py:209 +msgid " Kill Server" +msgstr "çµæ¢äŒºæåš" + +#: module/cli/Cli.py:210 +msgid " Quit" +msgstr "é¢é" + +#: module/cli/Cli.py:289 module/cli/Cli.py:296 +msgid "Please use this syntax: add <Package name> <link> <link2> ..." +msgstr "è«äœ¿çšæ€èªæ³: add ä»»ååçš±> <é£çµ> <é£çµ2> ..." + +#: module/cli/Cli.py:315 +#, python-format +msgid "Checking %d links:" +msgstr "æª¢æ¥ %d é£çµ:" + +#: module/cli/Cli.py:324 +msgid "File does not exists." +msgstr "æªæ¡äžååšã" + +#: module/cli/Cli.py:385 +msgid "pyLoad was terminated" +msgstr "pyLoad å·²çµæ¢" + +#: module/cli/Cli.py:443 +msgid "Prints server status" +msgstr "顯瀺䌺æåšçæ
" + +#: module/cli/Cli.py:444 +msgid "Prints downloads in queue" +msgstr "顯瀺äœåäžäžèŒé
ç®" + +#: module/cli/Cli.py:445 +msgid "Prints downloads in collector" +msgstr "顯瀺æ¶éåšäžäžèŒé
ç®" + +#: module/cli/Cli.py:446 +msgid "Adds package to queue" +msgstr "æ°å¢ä»»åå°äœå" + +#: module/cli/Cli.py:447 +msgid "Adds package to collector" +msgstr "æ°å¢ä»»åå°æ¶éåš" + +#: module/cli/Cli.py:448 +msgid "Delete Files from Queue/Collector" +msgstr "åŸäœå/æ¶éåšäžåªé€æªæ¡" + +#: module/cli/Cli.py:449 +msgid "Delete Packages from Queue/Collector" +msgstr "åŸäœå/æ¶éåšäžåªé€ä»»å" + +#: module/cli/Cli.py:450 +msgid "Move Packages from Queue to Collector or vice versa" +msgstr "åšäœåææ¶éåšäžç§»åä»»å" + +#: module/cli/Cli.py:451 +msgid "Restart files" +msgstr "éæ°éå§æªæ¡" + +#: module/cli/Cli.py:452 +msgid "Restart packages" +msgstr "éæ°éå§ä»»å" + +#: module/cli/Cli.py:453 +msgid "Check online status, works with local container" +msgstr "æ¥çç·äžçæ
ïŒå·¥äœèæ¬æ©å®¹åš" + +#: module/cli/Cli.py:454 +msgid "Checks online status of a container file" +msgstr "檢æ¥å®¹åšå
§æªæ¡äžç·çæ
" + +#: module/cli/Cli.py:455 +msgid "Pause the server" +msgstr "æ«å䌺æåš" + +#: module/cli/Cli.py:456 +msgid "continue downloads" +msgstr "繌çºäžèŒ" + +#: module/cli/Cli.py:457 +msgid "Toggle pause/unpause" +msgstr "æ«å/繌çº" + +#: module/cli/Cli.py:458 +msgid "kill server" +msgstr "çµæ¢äŒºæåš" + +#: module/cli/Cli.py:460 +msgid "List of commands:" +msgstr "åœä»€æž
å®ïŒ" + +#: module/cli/Cli.py:473 +msgid "Couldn't write user config file" +msgstr "äžèœå¯«å
¥äœ¿çšè
èšå®æª" + +#: module/cli/Cli.py:548 +msgid "You need py-openssl to connect to this pyLoad Core." +msgstr "æšéèŠå®è£
py-opensslæ¥è¿æ¥è¿äžªpyLoadæ žå¿ã" + +#: module/cli/Cli.py:555 +msgid "Address: " +msgstr "äœå:" + +#: module/cli/Cli.py:556 +msgid "Port: " +msgstr "飿¥å :" + +#: module/cli/Cli.py:557 +msgid "Username: " +msgstr "䜿çšè
åçš±:" + +#: module/cli/Cli.py:561 +msgid "Password: " +msgstr "å¯ç¢Œ:" + +#: module/cli/Cli.py:566 module/cli/Cli.py:575 +msgid "Login data is wrong." +msgstr "ç»å
¥è³èšé¯èª€ã" + +#: module/cli/Cli.py:568 module/cli/Cli.py:577 +#, python-format +msgid "Could not establish connection to %(addr)s:%(port)s." +msgstr "ç¡æ³å»ºç« %(addr)s:%(port)s é£ç·ã" + +#: module/cli/Cli.py:580 +msgid "You need py-openssl to connect to this pyLoad core." +msgstr "æšéèŠ py-openssl äŸé£æ¥ pyLoad æ žå¿ã" + +#: module/cli/Cli.py:582 +msgid "Interactive mode ignored since you passed some commands." +msgstr "å·è¡åœä»€äžïŒå¿œç¥äºåæš¡åŒã" + +#: module/cli/AddPackage.py:48 +msgid "Add Package:" +msgstr "æ°å¢äžèŒä»»åïŒ" + +#: module/cli/AddPackage.py:53 +msgid "Enter a name for the new package" +msgstr "茞å
¥æ°ä»»ååçš±" + +#: module/cli/AddPackage.py:57 +#, python-format +msgid "Package: %s" +msgstr "ä»»åïŒ%s" + +#: module/cli/AddPackage.py:58 +msgid "Parse the links you want to add." +msgstr "åæäœ æ³å å
¥çé£çµã" + +#: module/cli/AddPackage.py:59 +#, python-format +msgid "Type %s when done." +msgstr "宿åŸè«èŒžå
¥ %s" + +#: module/cli/AddPackage.py:60 +msgid "Links added: " +msgstr "å å
¥çé£çµ:" + +#: module/cli/AddPackage.py:64 module/cli/ManageFiles.py:149 +msgid " back to main menu" +msgstr "åå°äž»éžå®" + +#: module/cli/ManageFiles.py:97 +msgid "Manage Packages:" +msgstr "管çä»»å" + +#: module/cli/ManageFiles.py:99 +msgid "Manage Links:" +msgstr "管çé£çµïŒ" + +#: module/cli/ManageFiles.py:104 +msgid "What do you want to move?" +msgstr "äœ æ³èŠç§»å?" + +#: module/cli/ManageFiles.py:106 +msgid "What do you want to delete?" +msgstr "äœ æ³èŠåªé€?" + +#: module/cli/ManageFiles.py:108 +msgid "What do you want to restart?" +msgstr "äœ æ³èŠéå?" + +#: module/cli/ManageFiles.py:113 +msgid "Choose what yout want to do or enter package number." +msgstr "" + +#: module/cli/ManageFiles.py:115 +msgid "delete" +msgstr "åªé€" + +#: module/cli/ManageFiles.py:115 +msgid "move" +msgstr "ç§»å" + +#: module/cli/ManageFiles.py:115 +msgid "restart" +msgstr "éå" + +#: module/cli/ManageFiles.py:148 +msgid " - previous" +msgstr " - äžäžé " + +#: module/cli/ManageFiles.py:148 +msgid " - next" +msgstr "- äžäžé " + diff --git a/locale/zh/LC_MESSAGES/setup.po b/locale/zh/LC_MESSAGES/setup.po new file mode 100644 index 000000000..323d06cea --- /dev/null +++ b/locale/zh/LC_MESSAGES/setup.po @@ -0,0 +1,459 @@ +msgid "" +msgstr "Project-Id-Version: pyload\n" +"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" +"POT-Creation-Date: 2014-04-08 15:01+0200\n" +"PO-Revision-Date: 2014-04-09 05:38-0400\n" +"Last-Translator: pyloadTeam <team@pyload.org>\n" +"Language-Team: Chinese Traditional\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: crowdin.net\n" + +#: module/setup.py:51 +msgid "y" +msgstr "æ¯" + +#: module/setup.py:53 +msgid "n" +msgstr "åŠ" + +#: module/setup.py:72 +msgid "Welcome to the pyLoad Configuration Assistent." +msgstr "æ¡è¿äœ¿çšpyLoadèšå®å©æ" + +#: module/setup.py:73 +msgid "It will check your system and make a basic setup in order to run pyLoad." +msgstr "å®å°ææª¢æ¥æšçç³»çµ±äžŠå®æåºæ¬èšå®" + +#: module/setup.py:75 +msgid "The value in brackets [] always is the default value," +msgstr "äžæ¬åŒ§å
§çåŒçºé èšåŒ" + +#: module/setup.py:76 +msgid "in case you don't want to change it or you are unsure what to choose, just hit enter." +msgstr "åŠææšäžç¥é該åŠäœèšå®ææ¯äžéæ¹è®ïŒè«çŽæ¥æäžEnter" + +#: module/setup.py:78 +msgid "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyload.py ." +msgstr "å°æéïŒ æšä»¥åŸå¯ä»¥éépyLoadCore -s ææ¯ pyload.py --setupéæ°å·è¡èšå®å©æ" + +#: module/setup.py:79 +msgid "If you have any problems with this assistent hit STRG-C," +msgstr "åŠæäœ å¯¹æ¬å©çæä»»äœçé®ïŒè¯·æSTRG-CïŒ" + +#: module/setup.py:80 +msgid "to abort and don't let him start with pyload.py automatically anymore." +msgstr "äžåè®èšå®å©æèpyLoadåæåå" + +#: module/setup.py:82 +msgid "When you are ready for system check, hit enter." +msgstr "æäžç¢ºå®åŸéå§æª¢æ¥ç³»çµ±çæ
" + +#: module/setup.py:89 +msgid "You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad." +msgstr "äœ éèŠpycurlïŒsqlite以åpython 2.5ïŒ2.6ææ¯2.7æ¥è¿è¡pyLoadã" + +#: module/setup.py:90 +msgid "Please correct this and re-run pyLoad." +msgstr "请修æ¹åéæ°è¿è¡pyLoad" + +#: module/setup.py:91 +msgid "Setup will now close." +msgstr "å®è£
å富å
³éã" + +#: module/setup.py:95 +msgid "System check finished, hit enter to see your status report." +msgstr "ç³»ç»æ£æ¥å®æ¯ïŒæ©äžå蜊以æ¥çç³»ç»æ¥åã" + +#: module/setup.py:97 +msgid "## Status ##" +msgstr "ïŒïŒè¿çšïŒïŒ" + +#: module/setup.py:101 +msgid "container decrypting" +msgstr "" + +#: module/setup.py:102 +msgid "ssl connection" +msgstr "" + +#: module/setup.py:103 +msgid "automatic captcha decryption" +msgstr "" + +#: module/setup.py:104 +msgid "GUI" +msgstr "" + +#: module/setup.py:105 +msgid "Webinterface" +msgstr "Webçé¢" + +#: module/setup.py:106 +msgid "extended Click'N'Load" +msgstr "" + +#: module/setup.py:113 +msgid "Features available:" +msgstr "" + +#: module/setup.py:117 +msgid "Featues missing: " +msgstr "" + +#: module/setup.py:121 +msgid "no py-crypto available" +msgstr "" + +#: module/setup.py:122 +msgid "You need this if you want to decrypt container files." +msgstr "" + +#: module/setup.py:126 +msgid "no SSL available" +msgstr "" + +#: module/setup.py:127 +msgid "This is needed if you want to establish a secure connection to core or webinterface." +msgstr "" + +#: module/setup.py:128 +msgid "If you only want to access locally to pyLoad ssl is not usefull." +msgstr "" + +#: module/setup.py:132 +msgid "no Captcha Recognition available" +msgstr "" + +#: module/setup.py:133 +msgid "Only needed for some hosters and as freeuser." +msgstr "" + +#: module/setup.py:137 +msgid "Gui not available" +msgstr "" + +#: module/setup.py:138 +msgid "The Graphical User Interface." +msgstr "" + +#: module/setup.py:142 +msgid "no JavaScript engine found" +msgstr "" + +#: module/setup.py:143 +msgid "You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino" +msgstr "" + +#: module/setup.py:145 +msgid "You can abort the setup now and fix some dependicies if you want." +msgstr "" + +#: module/setup.py:147 +msgid "Continue with setup?" +msgstr "æ¯åŠç¹Œçºèšå®ïŒ" + +#: module/setup.py:153 +#, python-format +msgid "Do you want to change the config path? Current is %s" +msgstr "ç®ååæŸèšå®æªçäœçœ®çº %sïŒæ¯åŠèŠä¿®æ¹ïŒ" + +#: module/setup.py:155 +msgid "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it." +msgstr "" + +#: module/setup.py:156 +msgid "Change config path?" +msgstr "æ¹è®èšå®æè·¯åŸïŒ" + +#: module/setup.py:162 +msgid "Do you want to configure login data and basic settings?" +msgstr "æ¯åŠèŠé²è¡åºæ¬èšå®ïŒ" + +#: module/setup.py:163 +msgid "This is recommend for first run." +msgstr "ç¬¬äžæ¬¡äœ¿çšpyLoadæå»ºè°äœ¿çš" + +#: module/setup.py:164 +msgid "Make basic setup?" +msgstr "éå§åºç€èšå®åïŒ" + +#: module/setup.py:171 +msgid "Do you want to configure ssl?" +msgstr "éå§èšå®SSLåïŒ" + +#: module/setup.py:172 +msgid "Configure ssl?" +msgstr "èšå®SSLïŒ" + +#: module/setup.py:178 +msgid "Do you want to configure webinterface?" +msgstr "éå§èšå®ç¶²é ä»é¢ïŒ" + +#: module/setup.py:179 +msgid "Configure webinterface?" +msgstr "èšå®ç¶²é ä»é¢ïŒ" + +#: module/setup.py:184 +msgid "Setup finished successfully." +msgstr "èšå®å®æ" + +#: module/setup.py:185 +msgid "Hit enter to exit and restart pyLoad" +msgstr "æäžEnteré¢éèšå®ä»é¢äžŠéæ°ååpyLoad" + +#: module/setup.py:191 +msgid "## System Check ##" +msgstr "" + +#: module/setup.py:194 +msgid "Your python version is to new, Please use Python 2.6/2.7" +msgstr "" + +#: module/setup.py:197 +msgid "Your python version is to old, Please use at least Python 2.5" +msgstr "" + +#: module/setup.py:200 +msgid "Python Version: OK" +msgstr "" + +#: module/setup.py:247 +#, python-format +msgid "Your installed jinja2 version %s seems too old." +msgstr "" + +#: module/setup.py:248 +msgid "You can safely continue but if the webinterface is not working," +msgstr "" + +#: module/setup.py:249 +msgid "please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary." +msgstr "" + +#: module/setup.py:264 +msgid "JS engine" +msgstr "" + +#: module/setup.py:270 +msgid "## Basic Setup ##" +msgstr "ïŒïŒåºæ¬èšå®ïŒïŒ" + +#: module/setup.py:273 +msgid "The following logindata is valid for CLI, GUI and webinterface." +msgstr "äžåèšæ¯åšCLIãGUIåç¶²é ä»é¢çæ¯ææç" + +#: module/setup.py:279 module/setup.py:370 module/setup.py:386 +msgid "Username" +msgstr "䜿çšè
åçš±" + +#: module/setup.py:285 +msgid "External clients (GUI, CLI or other) need remote access to work over the network." +msgstr "" + +#: module/setup.py:286 +msgid "However, if you only want to use the webinterface you may disable it to save ram." +msgstr "" + +#: module/setup.py:287 +msgid "Enable remote access" +msgstr "" + +#: module/setup.py:291 +msgid "Language" +msgstr "èªèš" + +#: module/setup.py:293 +msgid "Downloadfolder" +msgstr "" + +#: module/setup.py:294 +msgid "Max parallel downloads" +msgstr "忿倧äžèŒæžé" + +#: module/setup.py:298 +msgid "Use Reconnect?" +msgstr "éåé詊æ©å¶ïŒ" + +#: module/setup.py:301 +msgid "Reconnect script location" +msgstr "é詊è
³æ¬è·¯åŸ" + +#: module/setup.py:306 +msgid "## Webinterface Setup ##" +msgstr "ïŒïŒç¶²é ä»é¢èšå®ïŒïŒ" + +#: module/setup.py:309 +msgid "Activate webinterface?" +msgstr "éåç¶²é ä»é¢ïŒ" + +#: module/setup.py:311 +msgid "Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally." +msgstr "ç£èœäœåïŒäœ¿çš127.0.0.1ælocalhostïŒå¯è®ç¶²é ä»é¢åªæåšæ¬å°ç«¯å¯äœ¿çš" + +#: module/setup.py:312 +msgid "Address" +msgstr "IPäœå" + +#: module/setup.py:313 +msgid "Port" +msgstr "å " + +#: module/setup.py:315 +msgid "pyLoad offers several server backends, now following a short explanation." +msgstr "pyLoadæäŸäºå¹Ÿçš®serveræš¡åŒïŒä»¥äžäœç°¡ç說æ" + +#: module/setup.py:316 +msgid "Default server, best choice if you dont know which one to choose." +msgstr "" + +#: module/setup.py:317 +msgid "This server offers SSL and is a good alternative to builtin." +msgstr "" + +#: module/setup.py:319 +msgid "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job." +msgstr "åé©ç¶çèšå®åŸå¯ä»¥è¢«apacheãlighttpd䜿çšïŒå°æ¥æš¡åŒïŒ" + +#: module/setup.py:320 +msgid "Very fast alternative written in C, requires libev and linux knowlegde." +msgstr "" + +#: module/setup.py:321 +msgid "Get it from here: https://github.com/jonashaag/bjoern, compile it" +msgstr "ç±æ€äžèŒ ïŒhttps://github.com/jonashaag/bjoernïŒäžŠç·šè¯" + +#: module/setup.py:322 +msgid "and copy bjoern.so to module/lib" +msgstr "" + +#: module/setup.py:326 +msgid "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface" +msgstr "èŠåïŒå
§å»º(buildin)䌺æåšåšæäºæ
æ³æç¡æ³éäœ" + +#: module/setup.py:327 +msgid "come back here and change the builtin server to the threaded one here." +msgstr "åŠæäœ çŒçŸç¶²é ä»é¢æä»»äœåé¡ïŒè«éæ°å·è¡èšå®å©æäžŠå°äŒºæåšæš¡åŒèšå®çºå
¶é€æš¡åŒ" + +#: module/setup.py:329 +msgid "Server" +msgstr "䌺æåš" + +#: module/setup.py:334 +msgid "## SSL Setup ##" +msgstr "ïŒïŒSSLèšå®ïŒïŒ" + +#: module/setup.py:336 +msgid "Execute these commands from pyLoad config folder to make ssl certificates:" +msgstr "åšpyLoadèšå®æªç®éäžå·è¡äžåæä»€ä»¥ååŸSSLæè" + +#: module/setup.py:342 +msgid "If you're done and everything went fine, you can activate ssl now." +msgstr "åŠæäžåé å©çŸåšå°±å¯ä»¥éåSSL" + +#: module/setup.py:344 +msgid "Activate SSL?" +msgstr "åçšSSLïŒ" + +#: module/setup.py:360 +msgid "Select action" +msgstr "éžæåäœ " + +#: module/setup.py:361 +msgid "1 - Create/Edit user" +msgstr "1. å»ºç«æç·šèŒ¯äœ¿çšè
" + +#: module/setup.py:362 +msgid "2 - List users" +msgstr "2. ååºææäœ¿çšè
" + +#: module/setup.py:363 +msgid "3 - Remove user" +msgstr "3. åªé€äœ¿çšè
" + +#: module/setup.py:364 +msgid "4 - Quit" +msgstr "4. é¢é" + +#: module/setup.py:376 +msgid "Users" +msgstr "䜿çšè
" + +#: module/setup.py:403 +msgid "Setting new configpath, current configuration will not be transfered!" +msgstr "" + +#: module/setup.py:404 +msgid "Configpath" +msgstr "" + +#: module/setup.py:412 +msgid "Configpath changed, setup will now close, please restart to go on." +msgstr "" + +#: module/setup.py:413 +msgid "Press Enter to exit." +msgstr "æäž Enter é¢éã" + +#: module/setup.py:417 +#, python-format +msgid "Setting config path failed: %s" +msgstr "èšå®æªè·¯åŸæèª€ %s" + +#: module/setup.py:422 +#, python-format +msgid "%s: OK" +msgstr "" + +#: module/setup.py:424 +#, python-format +msgid "%s: missing" +msgstr "" + +#: module/setup.py:464 +msgid "Password: " +msgstr "å¯ç¢Œ:" + +#: module/setup.py:468 +msgid "Password too short. Use at least 4 symbols." +msgstr "å¯ç¢Œè³å°éèŠåååå
" + +#: module/setup.py:471 +msgid "Password (again): " +msgstr "å茞å
¥äžæ¬¡å¯ç¢ŒïŒ" + +#: module/setup.py:477 +msgid "Passwords did not match." +msgstr "å¯ç äžç¬Š" + +#: module/setup.py:493 +msgid "yes" +msgstr "æ¯" + +#: module/setup.py:493 +msgid "true" +msgstr "æ¯" + +#: module/setup.py:493 +msgid "t" +msgstr "" + +#: module/setup.py:496 +msgid "no" +msgstr "åŠ" + +#: module/setup.py:496 +msgid "false" +msgstr "åŠ" + +#: module/setup.py:496 +msgid "f" +msgstr "" + +#: module/setup.py:499 module/setup.py:509 +msgid "Invalid Input" +msgstr "äžåæ³ç茞å
¥" + diff --git a/module/Api.py b/module/Api.py index f0bf5e264..066d490ec 100644 --- a/module/Api.py +++ b/module/Api.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -49,7 +48,7 @@ def permission(bits): def __new__(cls, func, *args, **kwargs): permMap[func.__name__] = bits return func - + return _Dec @@ -160,7 +159,7 @@ class Api(Iface): @permission(PERMS.SETTINGS) def getConfig(self): """Retrieves complete config of core. - + :return: list of `ConfigSection` """ return self._convertConfigFormat(self.core.config.config) @@ -219,7 +218,7 @@ class Api(Iface): @permission(PERMS.LIST) def statusServer(self): """Some general information about the current status of pyLoad. - + :return: `ServerStatus` """ serverStatus = ServerStatus(self.core.threadManager.pause, len(self.core.threadManager.processingIds()), @@ -484,7 +483,7 @@ class Api(Iface): :return: `PackageData` with .fid attribute """ data = self.core.files.getPackageData(int(pid)) - + if not data: raise PackageDoesNotExists(pid) @@ -511,7 +510,7 @@ class Api(Iface): @permission(PERMS.DELETE) def deleteFiles(self, fids): """Deletes several file entries from pyload. - + :param fids: list of file ids """ for id in fids: @@ -584,7 +583,7 @@ class Api(Iface): @permission(PERMS.ADD) def addFiles(self, pid, links): """Adds files to specific package. - + :param pid: package id :param links: list of urls """ @@ -923,10 +922,8 @@ class Api(Iface): """ if self.core.config["remote"]["nolocalauth"] and remoteip == "127.0.0.1": return "local" - if self.core.startedInGui and remoteip == "127.0.0.1": - return "local" - - return self.core.db.checkAuth(username, password) + else: + return self.core.db.checkAuth(username, password) def isAuthorized(self, func, userdata): """checks if the user is authorized for specific method @@ -1011,7 +1008,7 @@ class Api(Iface): def getAllInfo(self): """Returns all information stored by hook plugins. Values are always strings - :return: {"plugin": {"name": value } } + :return: {"plugin": {"name": value}} """ return self.core.hookManager.getAllInfo() @@ -1030,4 +1027,4 @@ class Api(Iface): def setUserPermission(self, user, permission, role): self.core.db.setPermission(user, permission) - self.core.db.setRole(user, role)
\ No newline at end of file + self.core.db.setRole(user, role) diff --git a/module/CaptchaManager.py b/module/CaptchaManager.py index 02cd10a11..0ba876ae8 100644 --- a/module/CaptchaManager.py +++ b/module/CaptchaManager.py @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: mkaay, RaNaN """ @@ -21,7 +21,7 @@ from time import time from traceback import print_exc from threading import Lock -class CaptchaManager(): +class CaptchaManager: def __init__(self, core): self.lock = Lock() self.core = core @@ -70,7 +70,7 @@ class CaptchaManager(): except: if self.core.debug: print_exc() - + if task.handler or cli: #the captcha was handled self.tasks.append(task) return True @@ -80,7 +80,7 @@ class CaptchaManager(): return False -class CaptchaTask(): +class CaptchaTask: def __init__(self, id, img, format, file, result_type='textual'): self.id = str(id) self.captchaImg = img diff --git a/module/ConfigParser.py b/module/ConfigParser.py index 78b612f13..9de405a3d 100644 --- a/module/ConfigParser.py +++ b/module/ConfigParser.py @@ -19,22 +19,21 @@ CONF_VERSION = 1 class ConfigParser: """ holds and manage the configuration - + current dict layout: - + { - - section : { - option : { + + section: { + option: { value: type: desc: } desc: - + } - - + """ @@ -372,21 +371,3 @@ class Section: def __setitem__(self, item, value): """setitem""" self.parser.set(self.section, item, value) - - -if __name__ == "__main__": - pypath = "" - - from time import time - - a = time() - - c = ConfigParser() - - b = time() - - print "sec", b - a - - print c.config - - c.saveConfig(c.config, "user.conf") diff --git a/pyLoadCore.py b/module/Core.py index 35cac4682..a3156d804 100755..100644 --- a/pyLoadCore.py +++ b/module/Core.py @@ -18,9 +18,9 @@ @author: sebnapi @author: RaNaN @author: mkaay - @version: v0.4.9 + @version: v0.4.10 """ -CURRENT_VERSION = '0.4.9' +CURRENT_VERSION = '0.4.10' import __builtin__ @@ -46,7 +46,7 @@ from module.ConfigParser import ConfigParser from module.plugins.PluginManager import PluginManager from module.PullEvents import PullManager from module.network.RequestFactory import RequestFactory -from module.web.ServerThread import WebServer +from module.threads.ServerThread import WebServer from module.Scheduler import Scheduler from module.common.JsEngine import JsEngine from module import remote @@ -69,7 +69,6 @@ class Core(object): def __init__(self): self.doDebug = False - self.startedInGui = False self.running = False self.daemon = False self.remote = True @@ -143,21 +142,21 @@ class Core(object): exit() def print_help(self): - print "" - print "pyLoad v%s 2008-2011 the pyLoad Team" % CURRENT_VERSION - print "" + print + print "pyLoad v%s 2008-2014 the pyLoad Team" % CURRENT_VERSION + print if sys.argv[0].endswith(".py"): - print "Usage: python pyLoadCore.py [options]" + print "Usage: python pyload.py [options]" else: - print "Usage: pyLoadCore [options]" - print "" + print "Usage: pyload [options]" + print print "<Options>" print " -v, --version", " " * 10, "Print version to terminal" print " -c, --clear", " " * 12, "Delete all saved packages/links" #print " -a, --add=<link/list>", " " * 2, "Add the specified links" print " -u, --user", " " * 13, "Manages users" print " -d, --debug", " " * 12, "Enable debug mode" - print " -s, --setup", " " * 12, "Run Setup Assistent" + print " -s, --setup", " " * 12, "Run Setup Assistant" print " --configdir=<dir>", " " * 6, "Run with <dir> as config directory" print " -p, --pidfile=<file>", " " * 3, "Set pidfile to <file>" print " --changedir", " " * 12, "Change config dir permanently" @@ -167,7 +166,7 @@ class Core(object): print " --clean", " " * 16, "Remove .pyc/.pyo files" print " -q, --quit", " " * 13, "Quit running pyLoad instance" print " -h, --help", " " * 13, "Display this help screen" - print "" + print def toggle_pause(self): if self.threadManager.pause: @@ -292,7 +291,7 @@ class Core(object): gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) translation = gettext.translation("pyLoad", self.path("locale"), - languages=[self.config['general']['language'],"en"],fallback=True) + languages=[self.config['general']['language'], "en"], fallback=True) translation.install(True) self.debug = self.doDebug or self.config['general']['debug_mode'] @@ -348,12 +347,12 @@ class Core(object): self.log.debug("Remote activated: %s" % self.remote) self.check_install("Crypto", _("pycrypto to decode container files")) - #img = self.check_install("Image", _("Python Image Libary (PIL) for captcha reading")) + #img = self.check_install("Image", _("Python Image Library (PIL) for captcha reading")) #self.check_install("pycurl", _("pycurl to download any files"), True, True) self.check_file("tmp", _("folder for temporary files"), True) #tesser = self.check_install("tesseract", _("tesseract for captcha reading"), False) if os.name != "nt" else True - self.captcha = True # checks seems to fail, althoug tesseract is available + self.captcha = True # checks seems to fail, although tesseract is available self.check_file(self.config['general']['download_folder'], _("folder for downloads"), True) @@ -365,7 +364,7 @@ class Core(object): self.log.info(_("Moving old user config to DB")) self.db.addUser(self.config.oldRemoteData["username"], self.config.oldRemoteData["password"]) - self.log.info(_("Please check your logindata with ./pyLoadCore.py -u")) + self.log.info(_("Please check your logindata with ./pyload.py -u")) if self.deleteLinks: self.log.info(_("All links removed")) @@ -567,7 +566,7 @@ class Core(object): self.shutdown() chdir(owd) # close some open fds - for i in range(3,50): + for i in range(3, 50): try: close(i) except : @@ -647,9 +646,6 @@ def deamon(): def main(): - #change name to 'pyLoadCore' - #from module.lib.rename_process import renameProcess - #renameProcess('pyLoadCore') if "--daemon" in sys.argv: deamon() else: @@ -665,4 +661,3 @@ def main(): # And so it begins... if __name__ == "__main__": main() - diff --git a/module/HookManager.py b/module/HookManager.py index 16f692d76..6fd1162a7 100644 --- a/module/HookManager.py +++ b/module/HookManager.py @@ -25,7 +25,7 @@ from threading import RLock from types import MethodType -from module.PluginThread import HookThread +from module.threads.PluginThread import HookThread from module.plugins.PluginManager import literal_eval from utils import lock @@ -123,10 +123,10 @@ class HookManager: try: #hookClass = getattr(plugin, plugin.__name__) - if self.core.config.getPlugin(pluginname, "activated"): + if self.config.getPlugin(pluginname, "activated"): pluginClass = self.core.pluginManager.loadClass("hooks", pluginname) if not pluginClass: continue - + plugin = pluginClass(self.core, self) plugins.append(plugin) self.pluginMap[pluginClass.__name__] = plugin @@ -219,10 +219,7 @@ class HookManager: def downloadFinished(self, pyfile): for plugin in self.plugins: if plugin.isActivated(): - if "downloadFinished" in plugin.__threaded__: - self.startThread(plugin.downloadFinished, pyfile) - else: - plugin.downloadFinished(pyfile) + plugin.downloadFinished(pyfile) self.dispatchEvent("downloadFinished", pyfile) @@ -231,10 +228,7 @@ class HookManager: def downloadFailed(self, pyfile): for plugin in self.plugins: if plugin.isActivated(): - if "downloadFailed" in plugin.__threaded__: - self.startThread(plugin.downloadFinished, pyfile) - else: - plugin.downloadFailed(pyfile) + plugin.downloadFailed(pyfile) self.dispatchEvent("downloadFailed", pyfile) @@ -242,10 +236,7 @@ class HookManager: def packageFinished(self, package): for plugin in self.plugins: if plugin.isActivated(): - if "packageFinished" in plugin.__threaded__: - self.startThread(plugin.packageFinished, package) - else: - plugin.packageFinished(package) + plugin.packageFinished(package) self.dispatchEvent("packageFinished", package) @@ -312,4 +303,3 @@ class HookManager: % (event, f, args, str(e))) if self.core.debug: traceback.print_exc() - diff --git a/module/InitHomeDir.py b/module/InitHomeDir.py index 156c9f932..b8ea29180 100644 --- a/module/InitHomeDir.py +++ b/module/InitHomeDir.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -16,7 +15,7 @@ @author: RaNaN - This modules inits working directories and global variables, pydir and homedir + This modules inits working directories and global variables, pydir and homedir """ from os import makedirs, path, chdir @@ -25,7 +24,8 @@ import sys from sys import argv, platform import __builtin__ -__builtin__.owd = path.abspath("") #original working directory + +__builtin__.owd = path.abspath("") # original working directory __builtin__.pypath = path.abspath(path.join(__file__, "..", "..")) sys.path.append(join(pypath, "module", "lib")) @@ -56,13 +56,9 @@ args = " ".join(argv[1:]) # dirty method to set configdir from commandline arguments if "--configdir=" in args: - pos = args.find("--configdir=") - end = args.find("-", pos + 12) - - if end == -1: - configdir = args[pos + 12:].strip() - else: - configdir = args[pos + 12:end].strip() + for aa in argv: + if aa.startswith("--configdir="): + configdir = aa.replace("--configdir=", "", 1).strip() elif path.exists(path.join(pypath, "module", "config", "configdir")): f = open(path.join(pypath, "module", "config", "configdir"), "rb") c = f.read().strip() diff --git a/module/PullEvents.py b/module/PullEvents.py index 5ec76765e..3835a34ac 100644 --- a/module/PullEvents.py +++ b/module/PullEvents.py @@ -13,26 +13,26 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: mkaay """ from time import time from module.utils import uniqify -class PullManager(): +class PullManager: def __init__(self, core): self.core = core self.clients = [] - + def newClient(self, uuid): self.clients.append(Client(uuid)) - + def clean(self): for n, client in enumerate(self.clients): if client.lastActive + 30 < time(): del self.clients[n] - + def getEvents(self, uuid): events = [] validUuid = False @@ -46,52 +46,52 @@ class PullManager(): if not validUuid: self.newClient(uuid) events = [ReloadAllEvent("queue").toList(), ReloadAllEvent("collector").toList()] - return uniqify(events, repr) - + return uniqify(events) + def addEvent(self, event): for client in self.clients: client.addEvent(event) -class Client(): +class Client: def __init__(self, uuid): self.uuid = uuid self.lastActive = time() self.events = [] - + def newEvents(self): return len(self.events) > 0 - + def popEvent(self): if not len(self.events): return None return self.events.pop(0) - + def addEvent(self, event): self.events.append(event) -class UpdateEvent(): +class UpdateEvent: def __init__(self, itype, iid, destination): assert itype == "pack" or itype == "file" assert destination == "queue" or destination == "collector" self.type = itype self.id = iid self.destination = destination - + def toList(self): return ["update", self.destination, self.type, self.id] -class RemoveEvent(): +class RemoveEvent: def __init__(self, itype, iid, destination): assert itype == "pack" or itype == "file" assert destination == "queue" or destination == "collector" self.type = itype self.id = iid self.destination = destination - + def toList(self): return ["remove", self.destination, self.type, self.id] -class InsertEvent(): +class InsertEvent: def __init__(self, itype, iid, after, destination): assert itype == "pack" or itype == "file" assert destination == "queue" or destination == "collector" @@ -99,22 +99,22 @@ class InsertEvent(): self.id = iid self.after = after self.destination = destination - + def toList(self): return ["insert", self.destination, self.type, self.id, self.after] -class ReloadAllEvent(): +class ReloadAllEvent: def __init__(self, destination): assert destination == "queue" or destination == "collector" self.destination = destination - + def toList(self): return ["reload", self.destination] -class AccountUpdateEvent(): +class AccountUpdateEvent: def toList(self): return ["account"] -class ConfigUpdateEvent(): +class ConfigUpdateEvent: def toList(self): return ["config"] diff --git a/module/PyFile.py b/module/PyFile.py index 3dede9360..69ccc4baf 100644 --- a/module/PyFile.py +++ b/module/PyFile.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,7 +55,7 @@ class PyFile(object): def __init__(self, manager, id, url, name, size, status, error, pluginname, package, order): self.m = manager - + self.id = int(id) self.url = url self.name = name @@ -69,19 +68,19 @@ class PyFile(object): # database information ends here self.lock = RLock() - + self.plugin = None #self.download = None - + self.waitUntil = 0 # time() + time to wait - + # status attributes self.active = False #obsolete? self.abort = False self.reconnected = False self.statusname = None - + self.progress = 0 self.maxprogress = 100 @@ -90,7 +89,7 @@ class PyFile(object): # will convert all sizes to ints size = property(lambda self: self._size, setSize) - + def __repr__(self): return "PyFile %s: %s@%s" % (self.id, self.name, self.pluginname) @@ -109,7 +108,7 @@ class PyFile(object): :return: """ return hasattr(self, "plugin") and self.plugin - + def package(self): """ return package instance""" return self.m.getPackage(self.packageid) @@ -127,10 +126,10 @@ class PyFile(object): return self.m.statusMsg[self.status] else: return self.statusname - + def hasStatus(self, status): return statusMap[status] == self.status - + def sync(self): """sync PyFile instance with database""" self.m.updateLink(self) @@ -189,19 +188,19 @@ class PyFile(object): if self.plugin and self.plugin.req: self.plugin.req.abortDownloads() sleep(0.1) - + self.abort = False if self.hasPlugin() and self.plugin.req: self.plugin.req.abortDownloads() self.release() - + def finishIfDone(self): """set status to finish and release file if every thread is finished with it""" if self.id in self.m.core.threadManager.processingIds(): return False - + self.setStatus("finished") self.release() self.m.checkAllLinksFinished() @@ -209,17 +208,17 @@ class PyFile(object): def checkIfProcessed(self): self.m.checkAllLinksProcessed(self.id) - + def formatWait(self): """ formats and return wait time in humanreadable format """ seconds = self.waitUntil - time() - + if seconds < 0: return "00:00:00" - + hours, seconds = divmod(seconds, 3600) minutes, seconds = divmod(seconds, 60) return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - + def formatSize(self): """ formats size to readable format """ return formatSize(self.getSize()) @@ -227,34 +226,34 @@ class PyFile(object): def formatETA(self): """ formats eta to readable format """ seconds = self.getETA() - + if seconds < 0: return "00:00:00" - + hours, seconds = divmod(seconds, 3600) minutes, seconds = divmod(seconds, 60) return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - + def getSpeed(self): """ calculates speed """ try: return self.plugin.req.speed except: return 0 - + def getETA(self): """ gets established time of arrival""" try: return self.getBytesLeft() / self.getSpeed() except: return 0 - + def getBytesLeft(self): """ gets bytes left """ try: - return self.plugin.req.size - self.plugin.req.arrived + return self.getSize() - self.plugin.req.arrived except: return 0 - + def getPercent(self): """ get % of download """ if self.status == 12: @@ -264,7 +263,7 @@ class PyFile(object): return 0 else: return self.progress - + def getSize(self): """ get size of download """ try: @@ -274,7 +273,7 @@ class PyFile(object): return self.size except: return self.size - + def notifyChange(self): e = UpdateEvent("file", self.id, "collector" if not self.package().queue else "queue") self.m.core.pullManager.addEvent(e) diff --git a/module/PyPackage.py b/module/PyPackage.py index f3be6c886..01e67051c 100644 --- a/module/PyPackage.py +++ b/module/PyPackage.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,9 +17,9 @@ """ from module.PullEvents import UpdateEvent -from module.utils import save_path +from module.utils import safe_path -class PyPackage(): +class PyPackage: """ Represents a package object at runtime """ @@ -39,7 +38,7 @@ class PyPackage(): @property def folder(self): - return save_path(self._folder) + return safe_path(self._folder) def toDict(self): """ Returns a dictionary representation of the data. @@ -74,7 +73,7 @@ class PyPackage(): def delete(self): self.m.deletePackage(self.id) - + def notifyChange(self): e = UpdateEvent("pack", self.id, "collector" if not self.queue else "queue") self.m.core.pullManager.addEvent(e) diff --git a/module/Scheduler.py b/module/Scheduler.py index 0bc396b69..71b5f96af 100644 --- a/module/Scheduler.py +++ b/module/Scheduler.py @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: mkaay """ @@ -26,7 +26,7 @@ class AlreadyCalled(Exception): pass -class Deferred(): +class Deferred: def __init__(self): self.call = [] self.result = () @@ -44,7 +44,7 @@ class Deferred(): f(*args ** kwargs) -class Scheduler(): +class Scheduler: def __init__(self, core): self.core = core @@ -88,7 +88,7 @@ class Scheduler(): break -class Job(): +class Job: def __init__(self, time, call, args=[], kwargs={}, deferred=None, threaded=True): self.time = float(time) self.call = call @@ -111,7 +111,7 @@ class Job(): self.run() -class PriorityQueue(): +class PriorityQueue: """ a non blocking priority queue """ def __init__(self): @@ -138,4 +138,4 @@ class PriorityQueue(): except IndexError: return None, None finally: - self.lock.release()
\ No newline at end of file + self.lock.release() diff --git a/module/ThreadManager.py b/module/ThreadManager.py index 8937f4a29..bdc6ca6e2 100644 --- a/module/ThreadManager.py +++ b/module/ThreadManager.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ @@ -28,7 +27,7 @@ from random import choice import pycurl -import PluginThread +from module.threads import PluginThread from module.PyFile import PyFile from module.network.RequestFactory import getURL from module.utils import freeSpace, lock @@ -146,7 +145,7 @@ class ThreadManager: self.log.warning("Assign job error", e) if self.core.debug: print_exc() - + sleep(0.5) self.assignJob() #it may be failed non critical so we try it again @@ -156,7 +155,7 @@ class ThreadManager: self.infoResults.clear() self.log.debug("Cleared Result cache") - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def tryReconnect(self): """checks if reconnect needed""" @@ -227,7 +226,7 @@ class ThreadManager: return ip - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def checkThreadCount(self): """checks if there are need for increasing or reducing thread count""" @@ -251,7 +250,7 @@ class ThreadManager: self.log.debug("Cleaned up pycurl") return True - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def assignJob(self): """assing a job to a thread if possible""" @@ -262,12 +261,12 @@ class ThreadManager: free = [x for x in self.threads if not x.active] - inuse = set([(x.active.pluginname,self.getLimit(x)) for x in self.threads if x.active and x.active.hasPlugin() and x.active.plugin.account]) - inuse = map(lambda x : (x[0], x[1], len([y for y in self.threads if y.active and y.active.pluginname == x[0]])) ,inuse) + inuse = set([(x.active.pluginname, self.getLimit(x)) for x in self.threads if x.active and x.active.hasPlugin() and x.active.plugin.account]) + inuse = map(lambda x: (x[0], x[1], len([y for y in self.threads if y.active and y.active.pluginname == x[0]])) ,inuse) onlimit = [x[0] for x in inuse if x[1] > 0 and x[2] >= x[1]] occ = [x.active.pluginname for x in self.threads if x.active and x.active.hasPlugin() and not x.active.plugin.multiDL] + onlimit - + occ.sort() occ = tuple(set(occ)) job = self.core.files.getJob(occ) @@ -310,7 +309,7 @@ class ThreadManager: thread = PluginThread.DecrypterThread(self, job) def getLimit(self, thread): - limit = thread.active.plugin.account.getAccountData(thread.active.plugin.user)["options"].get("limitDL",["0"])[0] + limit = thread.active.plugin.account.getAccountData(thread.active.plugin.user)["options"].get("limitDL", ["0"])[0] return int(limit) def cleanup(self): diff --git a/module/cli/AddPackage.py b/module/cli/AddPackage.py index a73401586..16b32b9ee 100644 --- a/module/cli/AddPackage.py +++ b/module/cli/AddPackage.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # -#Copyright (C) 2011 RaNaN +#Copyright (C) 2011-2014 RaNaN # #This program is free software; you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by @@ -63,4 +62,4 @@ class AddPackage(Handler): println(line, "") println(line + 1, mag("0.") + _(" back to main menu")) - return line + 2
\ No newline at end of file + return line + 2 diff --git a/pyLoadCli.py b/module/cli/Cli.py index 079cee19c..929cf9881 100755..100644 --- a/pyLoadCli.py +++ b/module/cli/Cli.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # -#Copyright (C) 2011 RaNaN +#Copyright (C) 2008-2014 RaNaN # #This program is free software; you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by @@ -57,7 +56,7 @@ class Cli: self.command = command if not self.command: - renameProcess('pyLoadCli') + renameProcess('pyload-cli') self.getch = Getch() self.input = "" self.inputline = 0 @@ -392,12 +391,12 @@ class RefreshThread(Thread): def print_help(config): print - print "pyLoadCli Copyright (c) 2008-2011 the pyLoad Team" + print "pyLoad CLI Copyright (c) 2008-2014 the pyLoad Team" print - print "Usage: [python] pyLoadCli.py [options] [command]" + print "Usage: [python] pyload-cli.py [options] [command]" print print "<Commands>" - print "See pyLoadCli.py -c for a complete listing." + print "See pyload-cli.py -c for a complete listing." print print "<Options>" print " -i, --interactive", " Start in interactive mode" @@ -465,7 +464,7 @@ def print_commands(): def writeConfig(opts): try: - with open(join(homedir, ".pyloadcli"), "w") as cfgfile: + with open(join(homedir, ".pyload-cli"), "w") as cfgfile: cfgfile.write("[cli]") for opt in opts: cfgfile.write("%s=%s\n" % (opt, opts[opt])) @@ -484,15 +483,15 @@ def main(): config["language"] = "en" configFile = ConfigParser.ConfigParser() - configFile.read(join(homedir, ".pyloadcli")) + configFile.read(join(homedir, ".pyload-cli")) if configFile.has_section("cli"): for opt in configFile.items("cli"): config[opt[0]] = opt[1] gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) - translation = gettext.translation("pyLoadCli", join(pypath, "locale"), - languages=[config["language"],"en"],fallback=True) + translation = gettext.translation("Cli", join(pypath, "locale"), + languages=[config["language"], "en"], fallback=True) translation.install(unicode=True) interactive = False @@ -517,8 +516,8 @@ def main(): elif option in ("-l", "--language"): config["language"] = params gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) - translation = gettext.translation("pyLoadCli", join(pypath, "locale"), - languages=[config["language"],"en"],fallback=True) + translation = gettext.translation("Cli", join(pypath, "locale"), + languages=[config["language"], "en"], fallback=True) translation.install(unicode=True) elif option in ("-h", "--help"): print_help(config) @@ -584,7 +583,3 @@ def main(): if client: writeConfig(config) cli = Cli(client, command) - - -if __name__ == "__main__": - main() diff --git a/module/cli/Handler.py b/module/cli/Handler.py index 476d09386..37b0d7b99 100644 --- a/module/cli/Handler.py +++ b/module/cli/Handler.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # -#Copyright (C) 2011 RaNaN +#Copyright (C) 2011-2014 RaNaN # #This program is free software; you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by @@ -45,4 +44,4 @@ class Handler: def renderBody(self, line): """ gets the line where to render output and should return the line number below its content """ - return line + 1
\ No newline at end of file + return line + 1 diff --git a/module/cli/ManageFiles.py b/module/cli/ManageFiles.py index 4d0377d9d..8f202c59d 100644 --- a/module/cli/ManageFiles.py +++ b/module/cli/ManageFiles.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # -#Copyright (C) 2011 RaNaN +#Copyright (C) 2011-2014 RaNaN # #This program is free software; you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by @@ -107,7 +106,7 @@ class ManageFiles(Handler): elif self.mode == "r": println(line, _("What do you want to restart?")) - println(line + 1, "Enter single number, comma seperated numbers or ranges. eg. 1,2,3 or 1-3.") + println(line + 1, "Enter single number, comma seperated numbers or ranges. eg. 1, 2, 3 or 1-3.") line += 2 else: println(line, _("Choose what yout want to do or enter package number.")) diff --git a/module/cli/__init__.py b/module/cli/__init__.py index fa8a09291..413c6a638 100644 --- a/module/cli/__init__.py +++ b/module/cli/__init__.py @@ -1,2 +1,4 @@ +# -*- coding: utf-8 -*- + from AddPackage import AddPackage -from ManageFiles import ManageFiles
\ No newline at end of file +from ManageFiles import ManageFiles diff --git a/module/cli/printer.py b/module/cli/printer.py index c62c1800e..0b2f5a0e3 100644 --- a/module/cli/printer.py +++ b/module/cli/printer.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- def blue(string): @@ -23,4 +22,4 @@ def white(string): return "\033[1;37m" + unicode(string) + "\033[0m" def println(line, content): - print "\033[" + str(line) + ";0H\033[2K" + content
\ No newline at end of file + print "\033[" + str(line) + ";0H\033[2K" + content diff --git a/module/common/APIExerciser.py b/module/common/APIExerciser.py index 96f5ce9cf..34b1529b5 100644 --- a/module/common/APIExerciser.py +++ b/module/common/APIExerciser.py @@ -23,7 +23,7 @@ def createURLs(): return urls -AVOID = (0,3,8) +AVOID = (0, 3, 8) idPool = 0 sumCalled = 0 @@ -154,4 +154,4 @@ class APIExerciser(Thread): self.api.getAccounts(False) def getCaptchaTask(self): - self.api.getCaptchaTask(False)
\ No newline at end of file + self.api.getCaptchaTask(False) diff --git a/module/common/ImportDebugger.py b/module/common/ImportDebugger.py index a997f7b0c..ae3aef629 100644 --- a/module/common/ImportDebugger.py +++ b/module/common/ImportDebugger.py @@ -16,4 +16,4 @@ class ImportDebugger(object): print name, path -sys.meta_path.append(ImportDebugger())
\ No newline at end of file +sys.meta_path.append(ImportDebugger()) diff --git a/module/common/JsEngine.py b/module/common/JsEngine.py index 576be2a1b..46789f64d 100644 --- a/module/common/JsEngine.py +++ b/module/common/JsEngine.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -78,7 +77,7 @@ if not ENGINE or DEBUG: except: pass -class JsEngine(): +class JsEngine: def __init__(self): self.engine = ENGINE self.init = False @@ -154,9 +153,3 @@ class JsEngine(): def error(self): return _("No js engine detected, please install either Spidermonkey, ossp-js, pyv8 or rhino") - -if __name__ == "__main__": - js = JsEngine() - - test = u'"Ì"+"À"' - js.eval(test)
\ No newline at end of file diff --git a/module/common/__init__.py b/module/common/__init__.py index de6d13128..e69de29bb 100644 --- a/module/common/__init__.py +++ b/module/common/__init__.py @@ -1,2 +0,0 @@ -__author__ = 'christian' -
\ No newline at end of file diff --git a/module/common/json_layer.py b/module/common/json_layer.py index 4d57a9f38..bb3937cdc 100644 --- a/module/common/json_layer.py +++ b/module/common/json_layer.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # abstraction layer for json operations diff --git a/module/common/packagetools.py b/module/common/packagetools.py index 5bfbcba95..d5ab4d182 100644 --- a/module/common/packagetools.py +++ b/module/common/packagetools.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # JDownloader/src/jd/controlling/LinkGrabberPackager.java import re @@ -136,20 +134,3 @@ def parseNames(files): packs[name] = [url] return packs - - -if __name__ == "__main__": - from os.path import join - from pprint import pprint - - f = open(join("..", "..", "testlinks2.txt"), "rb") - urls = [(x.strip(), x.strip()) for x in f.readlines() if x.strip()] - f.close() - - print "Having %d urls." % len(urls) - - packs = parseNames(urls) - - pprint(packs) - - print "Got %d urls." % sum([len(x) for x in packs.itervalues()]) diff --git a/pavement.py b/module/common/pavement.py index ac9a6fa1a..9d36e9c1d 100644 --- a/pavement.py +++ b/module/common/pavement.py @@ -1,12 +1,15 @@ # -*- coding: utf-8 -*- - from paver.easy import * from paver.setuputils import setup from paver.doctools import cog +import os import sys +import shutil import re +from glob import glob +from tempfile import mkdtemp from urllib import urlretrieve from subprocess import call, Popen, PIPE from zipfile import ZipFile @@ -23,9 +26,9 @@ if sys.version_info <= (2, 5): setup( name="pyload", - version="0.4.9", + version="0.4.10", description='Fast, lightweight and full featured download manager.', - long_description=open(PROJECT_DIR / "README").read(), + long_description=open(PROJECT_DIR / "README.md").read(), keywords = ('pyload', 'download-manager', 'one-click-hoster', 'download'), url="http://pyload.org", download_url='http://pyload.org/download', @@ -40,7 +43,7 @@ setup( include_package_data=True, exclude_package_data={'pyload': ['docs*', 'scripts*', 'tests*']}, #exluced from build but not from sdist # 'bottle >= 0.10.0' not in list, because its small and contain little modifications - install_requires=['thrift >= 0.8.0', 'jinja2', 'pycurl', 'Beaker', 'BeautifulSoup>=3.2, <3.3'] + extradeps, + install_requires=['thrift >= 0.8.0', 'jinja2', 'pycurl', 'Beaker', 'BeautifulSoup >= 3.2, < 3.3'] + extradeps, extras_require={ 'SSL': ["pyOpenSSL"], 'DLC': ['pycrypto'], @@ -91,7 +94,8 @@ options( ) # xgettext args -xargs = ["--from-code=utf-8", "--copyright-holder=pyLoad Team", "--package-name=pyLoad", +xargs = ["--language=Python", "--add-comments=L10N", + "--from-code=utf-8", "--copyright-holder=pyLoad Team", "--package-name=pyLoad", "--package-version=%s" % options.version, "--msgid-bugs-address='bugs@pyload.org'"] @task @@ -136,7 +140,7 @@ def get_source(options): file.chmod(0755) (pyload / ".hgtags").remove() - (pyload / ".hgignore").remove() + (pyload / ".gitignore").remove() #(pyload / "docs").rmtree() f = open(pyload / "__init__.py", "wb") @@ -165,7 +169,7 @@ def thrift(options): outdir = path("module") / "remote" / "thriftbackend" (outdir / "gen-py").rmtree() - cmd = [options.thrift.path, "-strict", "-o", outdir, "--gen", "py:slots,dynamic", outdir / "pyload.thrift"] + cmd = [options.thrift.path, "-strict", "-o", outdir, "--gen", "py:slots, dynamic", outdir / "pyload.thrift"] if options.gen: cmd.insert(len(cmd) - 1, "--gen") @@ -202,14 +206,13 @@ def compile_js(): @task def generate_locale(): - """ Generates localisation files """ + """ Generates localization files """ - EXCLUDE = ["BeautifulSoup.py", "module/gui", "module/cli", "web/locale", "web/ajax", "web/cnl", "web/pyload", + EXCLUDE = ["BeautifulSoup.py", "module/cli", "web/locale", "web/ajax", "web/cnl", "web/pyload", "setup.py"] - makepot("core", path("module"), EXCLUDE, "./pyLoadCore.py\n") + makepot("core", path("module"), EXCLUDE, "./pyload.py\n") - makepot("gui", path("module") / "gui", [], includes="./pyLoadGui.py\n") - makepot("cli", path("module") / "cli", [], includes="./pyLoadCli.py\n") + makepot("cli", path("module") / "cli", [], includes="./pyload-cli.py\n") makepot("setup", "", [], includes="./module/setup.py\n") EXCLUDE = ["ServerThread.py", "web/media/default"] @@ -241,6 +244,83 @@ def generate_locale(): @task +@cmdopts([ + ('key=', 'k', 'api key') +]) +def upload_translations(options): + """ Uploads the locale files to translation server """ + tmp = path(mkdtemp()) + + shutil.copy('locale/crowdin.yaml', tmp) + os.mkdir(tmp / 'pyLoad') + for f in glob('locale/*.pot'): + if os.path.isfile(f): + shutil.copy(f, tmp / 'pyLoad') + + config = tmp / 'crowdin.yaml' + content = open(config, 'rb').read() + content = content.format(key=options.key, tmp=tmp) + f = open(config, 'wb') + f.write(content) + f.close() + + call(['crowdin-cli', '-c', config, 'upload', 'source']) + + shutil.rmtree(tmp) + + print "Translations uploaded" + + +@task +@cmdopts([ + ('key=', 'k', 'api key') +]) +def download_translations(options): + """ Downloads the translated files from translation server """ + tmp = path(mkdtemp()) + + shutil.copy('locale/crowdin.yaml', tmp) + os.mkdir(tmp / 'pyLoad') + for f in glob('locale/*.pot'): + if os.path.isfile(f): + shutil.copy(f, tmp / 'pyLoad') + + config = tmp / 'crowdin.yaml' + content = open(config, 'rb').read() + content = content.format(key=options.key, tmp=tmp) + f = open(config, 'wb') + f.write(content) + f.close() + + call(['crowdin-cli', '-c', config, 'download']) + + for language in (tmp / 'pyLoad').listdir(): + if not language.isdir(): + continue + + target = path('locale') / language.basename() + print "Copy language %s" % target + if target.exists(): + shutil.rmtree(target) + + shutil.copytree(language, target) + + shutil.rmtree(tmp) + + +@task +def compile_translations(): + """ Compile PO files to MO """ + for language in path('locale').listdir(): + if not language.isdir(): + continue + + for f in glob(language / 'LC_MESSAGES' / '*.po'): + print "Compiling %s" % f + call(['msgfmt', '-o', f.replace('.po', '.mo'), f]) + + +@task def tests(): call(["nosetests2"]) diff --git a/module/common/pylgettext.py b/module/common/pylgettext.py index fb36fecee..cab631cf4 100644 --- a/module/common/pylgettext.py +++ b/module/common/pylgettext.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- from gettext import * diff --git a/tests/test_api.py b/module/common/test_api.py index f8901f731..f8901f731 100644 --- a/tests/test_api.py +++ b/module/common/test_api.py diff --git a/tests/test_json.py b/module/common/test_json.py index ff56e8f5a..320a42d4f 100644 --- a/tests/test_json.py +++ b/module/common/test_json.py @@ -45,4 +45,4 @@ class TestJson: except HTTPError, e: assert e.code == 404 else: - assert False
\ No newline at end of file + assert False diff --git a/module/config/default.conf b/module/config/default.conf index 2e9152ba2..3a513f122 100644 --- a/module/config/default.conf +++ b/module/config/default.conf @@ -1,43 +1,42 @@ version: 1 remote - "Remote": - int port : "Port" = 7227 - ip listenaddr : "Adress" = 0.0.0.0 - bool nolocalauth : "No authentication on local connections" = True - bool activated : "Activated" = True + int port : "Port" = 7227 + ip listenaddr : "Address" = 0.0.0.0 + bool nolocalauth : "No authentication on local connections" = True + bool activated : "Activated" = True ssl - "SSL": - bool activated : "Activated"= False - file cert : "SSL Certificate" = ssl.crt - file key : "SSL Key" = ssl.key -webinterface - "Webinterface": - bool activated : "Activated" = True - builtin;threaded;fastcgi;lightweight server : "Server" = builtin - bool https : "Use HTTPS" = False - ip host : "IP" = 0.0.0.0 - int port : "Port" = 8001 - str template : "Template" = default + bool activated : "Activated"= False + file cert : "SSL Certificate" = ssl.crt + file key : "SSL Key" = ssl.key +webinterface - "Web UI": + bool activated : "Activated" = True + builtin;threaded;fastcgi;lightweight server : "Server" = builtin + bool https : "Use HTTPS" = False + ip host : "IP" = 0.0.0.0 + int port : "Port" = 8001 + default;dark;flat theme : "Theme" = flat str prefix: "Path Prefix" = log - "Log": - bool file_log : "File Log" = True - folder log_folder : "Folder" = Logs - int log_count : "Count" = 5 - int log_size : "Size in kb" = 100 - bool log_rotate : "Log Rotate" = True + bool file_log : "File Log" = True + folder log_folder : "Folder" = Logs + int log_count : "Count" = 5 + int log_size : "Size in kb" = 100 + bool log_rotate : "Log Rotate" = True general - "General": - en;de;fr;it;es;nl;sv;ru;pl;cs;sr;pt_BR language : "Language" = en - folder download_folder : "Download Folder" = Downloads - bool debug_mode : "Debug Mode" = False - bool checksum : "Use Checksum" = False - int min_free_space : "Min Free Space (MB)" = 200 - bool folder_per_package : "Create folder for each package" = True - int renice : "CPU Priority" = 0 + en;de;fr;it;es;nl;sv;ru;pl;cs;sr;pt_BR language : "Language" = en + folder download_folder : "Download Folder" = Downloads + bool debug_mode : "Debug Mode" = False + int min_free_space : "Min Free Space (MB)" = 200 + bool folder_per_package : "Create folder for each package" = True + int renice : "CPU Priority" = 0 download - "Download": int chunks : "Max connections for one download" = 3 int max_downloads : "Max Parallel Downloads" = 3 int max_speed : "Max Download Speed in kb/s" = -1 bool limit_speed : "Limit Download Speed" = False str interface : "Download interface to bind (ip or Name)" = None - bool ipv6 : "Allow IPv6" = False + bool ipv6: "Allow IPv6" = False bool skip_existing : "Skip already existing files" = False permission - "Permissions": bool change_user : "Change user of running process" = False @@ -49,17 +48,17 @@ permission - "Permissions": str group : "Groupname" = users bool change_dl : "Change Group and User of Downloads" = False reconnect - "Reconnect": - bool activated : "Use Reconnect" = False - str method : "Method" = None - time startTime : "Start" = 0:00 - time endTime : "End" = 0:00 + bool activated : "Use Reconnect" = False + str method : "Method" = None + time startTime : "Start" = 0:00 + time endTime : "End" = 0:00 downloadTime - "Download Time": - time start : "Start" = 0:00 - time end : "End" = 0:00 + time start : "Start" = 0:00 + time end : "End" = 0:00 proxy - "Proxy": - str address : "Address" = "localhost" - int port : "Port" = 7070 - http;socks4;socks5 type : "Protocol" = http - str username : "Username" = None - password password : "Password" = None + str address : "Address" = "localhost" + int port : "Port" = 7070 + http;socks4;socks5 type : "Protocol" = http + str username : "Username" = None + password password : "Password" = None bool proxy : "Use Proxy" = False diff --git a/module/config/gui_default.xml b/module/config/gui_default.xml deleted file mode 100644 index 1faed776f..000000000 --- a/module/config/gui_default.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" ?> -<root> - <connections> - <connection default="True" type="local" id="33965310e19b4a869112c43b39a16440"> - <name>Local</name> - </connection> - </connections> - <mainWindow> - <state></state> - <geometry></geometry> - </mainWindow> - <language>en</language> -</root> diff --git a/module/database/DatabaseBackend.py b/module/database/DatabaseBackend.py index 9530390c3..df2660063 100644 --- a/module/database/DatabaseBackend.py +++ b/module/database/DatabaseBackend.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,13 +33,13 @@ except: DB_VERSION = 4 -class style(): +class style: db = None - + @classmethod def setDB(cls, db): cls.db = db - + @classmethod def inner(cls, f): @staticmethod @@ -48,7 +47,7 @@ class style(): if cls.db: return f(cls.db, *args, **kwargs) return x - + @classmethod def queue(cls, f): @staticmethod @@ -56,7 +55,7 @@ class style(): if cls.db: return cls.db.queue(f, *args, **kwargs) return x - + @classmethod def async(cls, f): @staticmethod @@ -65,14 +64,14 @@ class style(): return cls.db.async(f, *args, **kwargs) return x -class DatabaseJob(): +class DatabaseJob: def __init__(self, f, *args, **kwargs): self.done = Event() - + self.f = f self.args = args self.kwargs = kwargs - + self.result = None self.exception = False @@ -104,7 +103,7 @@ class DatabaseJob(): self.exception = e finally: self.done.set() - + def wait(self): self.done.wait() @@ -116,34 +115,34 @@ class DatabaseBackend(Thread): self.core = core self.jobs = Queue() - + self.setuplock = Event() - + style.setDB(self) - + def setup(self): self.start() self.setuplock.wait() - + def run(self): """main loop, which executes commands""" convert = self._checkVersion() #returns None or current version - + self.conn = sqlite3.connect("files.db") chmod("files.db", 0600) self.c = self.conn.cursor() #compatibility - + if convert is not None: self._convertDB(convert) - + self._createTables() self._migrateUser() self.conn.commit() - + self.setuplock.set() - + while True: j = self.jobs.get() if j == "quit": @@ -164,7 +163,7 @@ class DatabaseBackend(Thread): f.write(str(DB_VERSION)) f.close() return - + f = open("files.version", "rb") v = int(f.read().strip()) f.close() @@ -180,7 +179,7 @@ class DatabaseBackend(Thread): f.write(str(DB_VERSION)) f.close() return v - + def _convertDB(self, v): try: getattr(self, "_convertV%i" % v)() @@ -189,9 +188,9 @@ class DatabaseBackend(Thread): self.core.log.error(_("Filedatabase could NOT be converted.")) except: print "Filedatabase could NOT be converted." - - #--convert scripts start - + + #convert scripts start----------------------------------------------------- + def _convertV2(self): self.c.execute('CREATE TABLE IF NOT EXISTS "storage" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "identifier" TEXT NOT NULL, "key" TEXT NOT NULL, "value" TEXT DEFAULT "")') try: @@ -199,16 +198,16 @@ class DatabaseBackend(Thread): except: print "Database was converted from v2 to v3." self._convertV3() - + def _convertV3(self): self.c.execute('CREATE TABLE IF NOT EXISTS "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT NOT NULL, "email" TEXT DEFAULT "" NOT NULL, "password" TEXT NOT NULL, "role" INTEGER DEFAULT 0 NOT NULL, "permission" INTEGER DEFAULT 0 NOT NULL, "template" TEXT DEFAULT "default" NOT NULL)') try: self.manager.core.log.info(_("Database was converted from v3 to v4.")) except: print "Database was converted from v3 to v4." - - #--convert scripts end - + + #convert scripts end------------------------------------------------------- + def _createTables(self): """create tables for database""" @@ -222,7 +221,7 @@ class DatabaseBackend(Thread): SELECT p.id AS id, SUM(l.size) AS sizetotal, COUNT(l.id) AS linkstotal, linksdone, sizedone\ FROM packages p JOIN links l ON p.id = l.package LEFT OUTER JOIN\ (SELECT p.id AS id, COUNT(*) AS linksdone, SUM(l.size) AS sizedone \ - FROM packages p JOIN links l ON p.id = l.package AND l.status in (0,4,13) GROUP BY p.id) s ON s.id = p.id \ + FROM packages p JOIN links l ON p.id = l.package AND l.status in (0, 4, 13) GROUP BY p.id) s ON s.id = p.id \ GROUP BY p.id') #try to lower ids @@ -264,10 +263,10 @@ class DatabaseBackend(Thread): self.c.executemany("INSERT INTO users(name, password, email) VALUES (?, ?, ?)", users) move("pyload.db", "pyload.old.db") - + def createCursor(self): return self.conn.cursor() - + @style.async def commit(self): self.conn.commit() @@ -275,78 +274,32 @@ class DatabaseBackend(Thread): @style.queue def syncSave(self): self.conn.commit() - + @style.async def rollback(self): self.conn.rollback() - + def async(self, f, *args, **kwargs): - args = (self, ) + args + args = (self,) + args job = DatabaseJob(f, *args, **kwargs) self.jobs.put(job) - + def queue(self, f, *args, **kwargs): - args = (self, ) + args + args = (self,) + args job = DatabaseJob(f, *args, **kwargs) self.jobs.put(job) job.wait() return job.result - + @classmethod def registerSub(cls, klass): cls.subs.append(klass) - + @classmethod def unregisterSub(cls, klass): cls.subs.remove(klass) - + def __getattr__(self, attr): for sub in DatabaseBackend.subs: if hasattr(sub, attr): return getattr(sub, attr) - -if __name__ == "__main__": - db = DatabaseBackend() - db.setup() - - class Test(): - @style.queue - def insert(db): - c = db.createCursor() - for i in range(1000): - c.execute("INSERT INTO storage (identifier, key, value) VALUES (?, ?, ?)", ("foo", i, "bar")) - @style.async - def insert2(db): - c = db.createCursor() - for i in range(1000*1000): - c.execute("INSERT INTO storage (identifier, key, value) VALUES (?, ?, ?)", ("foo", i, "bar")) - - @style.queue - def select(db): - c = db.createCursor() - for i in range(10): - res = c.execute("SELECT value FROM storage WHERE identifier=? AND key=?", ("foo", i)) - print res.fetchone() - - @style.queue - def error(db): - c = db.createCursor() - print "a" - c.execute("SELECT myerror FROM storage WHERE identifier=? AND key=?", ("foo", i)) - print "e" - - db.registerSub(Test) - from time import time - start = time() - for i in range(100): - db.insert() - end = time() - print end-start - - start = time() - db.insert2() - end = time() - print end-start - - db.error() - diff --git a/module/database/FileDatabase.py b/module/database/FileDatabase.py index 7e7efb028..f01d02769 100644 --- a/module/database/FileDatabase.py +++ b/module/database/FileDatabase.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -68,12 +67,12 @@ class FileHandler: return func(*args) return new - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def save(self): """saves all data to backend""" self.db.commit() - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def syncSave(self): """saves all data to backend and waits until all data are written""" pyfiles = self.cache.values() @@ -131,7 +130,7 @@ class FileHandler: #@TODO change from reloadAll event to package update event self.core.pullManager.addEvent(ReloadAllEvent("collector")) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- @lock @change def addPackage(self, name, folder, queue=0): @@ -142,7 +141,7 @@ class FileHandler: self.core.pullManager.addEvent(e) return lastID - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- @lock @change def deletePackage(self, id): @@ -178,7 +177,7 @@ class FileHandler: pack.order -= 1 pack.notifyChange() - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- @lock @change def deleteLink(self, id): @@ -190,7 +189,7 @@ class FileHandler: pid = f.packageid e = RemoveEvent("file", id, "collector" if not f.package().queue else "queue") - + oldorder = f.order if id in self.core.threadManager.processingIds(): @@ -206,26 +205,26 @@ class FileHandler: p = self.getPackage(pid) if not len(p.getChildren()): p.delete() - + pyfiles = self.cache.values() for pyfile in pyfiles: if pyfile.packageid == pid and pyfile.order > oldorder: pyfile.order -= 1 pyfile.notifyChange() - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def releaseLink(self, id): """removes pyfile from cache""" if id in self.cache: del self.cache[id] - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def releasePackage(self, id): """removes package from cache""" if id in self.packageCache: del self.packageCache[id] - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def updateLink(self, pyfile): """updates link""" self.db.updateLink(pyfile) @@ -233,7 +232,7 @@ class FileHandler: e = UpdateEvent("file", pyfile.id, "collector" if not pyfile.package().queue else "queue") self.core.pullManager.addEvent(e) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def updatePackage(self, pypack): """updates a package""" self.db.updatePackage(pypack) @@ -241,7 +240,7 @@ class FileHandler: e = UpdateEvent("pack", pypack.id, "collector" if not pypack.queue else "queue") self.core.pullManager.addEvent(e) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def getPackage(self, id): """return package instance""" @@ -250,7 +249,7 @@ class FileHandler: else: return self.db.getPackage(id) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def getPackageData(self, id): """returns dict with package information""" pack = self.getPackage(id) @@ -274,7 +273,7 @@ class FileHandler: return pack - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def getFileData(self, id): """returns dict with file information""" if id in self.cache: @@ -282,7 +281,7 @@ class FileHandler: return self.db.getLinkData(id) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def getFile(self, id): """returns pyfile instance""" if id in self.cache: @@ -290,7 +289,7 @@ class FileHandler: else: return self.db.getFile(id) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- @lock def getJob(self, occ): """get suitable job""" @@ -434,7 +433,7 @@ class FileHandler: e = RemoveEvent("pack", id, "collector" if not p.queue else "queue") self.core.pullManager.addEvent(e) - + self.db.clearPackageOrder(p) p = self.db.getPackage(id) @@ -443,7 +442,7 @@ class FileHandler: self.db.updatePackage(p) self.db.reorderPackage(p, -1, True) - + packs = self.packageCache.values() for pack in packs: if pack.queue != queue and pack.order > oldorder: @@ -453,7 +452,7 @@ class FileHandler: self.db.commit() self.releasePackage(id) p = self.getPackage(id) - + e = InsertEvent("pack", id, p.order, "collector" if not p.queue else "queue") self.core.pullManager.addEvent(e) @@ -540,7 +539,7 @@ class FileHandler: urls = [] for pyfile in data.itervalues(): - if pyfile["status"] not in (0, 12, 13): + if pyfile["status"] not in (0, 12, 13): urls.append((pyfile["url"], pyfile["plugin"])) self.core.threadManager.createInfoThread(urls, pid) @@ -573,23 +572,23 @@ class FileHandler: """ restart all failed links """ self.db.restartFailed() -class FileMethods(): +class FileMethods: @style.queue def filecount(self, queue): """returns number of files in queue""" - self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=?", (queue, )) + self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=?", (queue,)) return self.c.fetchone()[0] @style.queue def queuecount(self, queue): """ number of files in queue not finished yet""" - self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status NOT IN (0,4)", (queue, )) + self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status NOT IN (0, 4)", (queue,)) return self.c.fetchone()[0] @style.queue def processcount(self, queue, fid): """ number of files which have to be proccessed """ - self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status IN (2,3,5,7,12) AND l.id != ?", (queue, str(fid))) + self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status IN (2, 3, 5, 7, 12) AND l.id != ?", (queue, str(fid))) return self.c.fetchone()[0] @style.inner @@ -600,7 +599,7 @@ class FileMethods(): return max + 1 else: return 0 - + @style.inner def _nextFileOrder(self, package): self.c.execute('SELECT MAX(linkorder) FROM links WHERE package=?', (package,)) @@ -609,7 +608,7 @@ class FileMethods(): return max + 1 else: return 0 - + @style.queue def addLink(self, url, name, plugin, package): order = self._nextFileOrder(package) @@ -618,7 +617,7 @@ class FileMethods(): @style.queue def addLinks(self, links, package): - """ links is a list of tupels (url,plugin)""" + """ links is a list of tupels (url, plugin)""" order = self._nextFileOrder(package) orders = [order + x for x in range(len(links))] links = [(x[0], x[0], x[1], package, o) for x, o in zip(links, orders)] @@ -658,7 +657,7 @@ class FileMethods(): } """ - self.c.execute('SELECT l.id,l.url,l.name,l.size,l.status,l.error,l.plugin,l.package,l.linkorder FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? ORDER BY l.linkorder', (q,)) + self.c.execute('SELECT l.id, l.url, l.name, l.size, l.status, l.error, l.plugin, l.package, l.linkorder FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? ORDER BY l.linkorder', (q,)) data = {} for r in self.c: data[r[0]] = { @@ -688,7 +687,7 @@ class FileMethods(): format: { - id: {'name': name ... 'links': {} }, ... + id: {'name': name ... 'links': {}}, ... } """ self.c.execute('SELECT p.id, p.name, p.folder, p.site, p.password, p.queue, p.packageorder, s.sizetotal, s.sizedone, s.linksdone, s.linkstotal \ @@ -713,11 +712,11 @@ class FileMethods(): } return data - + @style.queue def getLinkData(self, id): """get link information as dict""" - self.c.execute('SELECT id,url,name,size,status,error,plugin,package,linkorder FROM links WHERE id=?', (str(id), )) + self.c.execute('SELECT id, url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?', (str(id),)) data = {} r = self.c.fetchone() if not r: @@ -741,7 +740,7 @@ class FileMethods(): @style.queue def getPackageData(self, id): """get data about links for a package""" - self.c.execute('SELECT id,url,name,size,status,error,plugin,package,linkorder FROM links WHERE package=? ORDER BY linkorder', (str(id), )) + self.c.execute('SELECT id, url, name, size, status, error, plugin, package, linkorder FROM links WHERE package=? ORDER BY linkorder', (str(id),)) data = {} for r in self.c: @@ -764,22 +763,22 @@ class FileMethods(): @style.async def updateLink(self, f): - self.c.execute('UPDATE links SET url=?,name=?,size=?,status=?,error=?,package=? WHERE id=?', (f.url, f.name, f.size, f.status, f.error, str(f.packageid), str(f.id))) + self.c.execute('UPDATE links SET url=?, name=?, size=?, status=?, error=?, package=? WHERE id=?', (f.url, f.name, f.size, f.status, f.error, str(f.packageid), str(f.id))) @style.queue def updatePackage(self, p): - self.c.execute('UPDATE packages SET name=?,folder=?,site=?,password=?,queue=? WHERE id=?', (p.name, p.folder, p.site, p.password, p.queue, str(p.id))) - + self.c.execute('UPDATE packages SET name=?, folder=?, site=?, password=?, queue=? WHERE id=?', (p.name, p.folder, p.site, p.password, p.queue, str(p.id))) + @style.queue def updateLinkInfo(self, data): """ data is list of tupels (name, size, status, url) """ - self.c.executemany('UPDATE links SET name=?, size=?, status=? WHERE url=? AND status IN (1,2,3,14)', data) + self.c.executemany('UPDATE links SET name=?, size=?, status=? WHERE url=? AND status IN (1, 2, 3, 14)', data) ids = [] self.c.execute('SELECT id FROM links WHERE url IN (\'%s\')' % "','".join([x[3] for x in data])) for r in self.c: ids.append(int(r[0])) return ids - + @style.queue def reorderPackage(self, p, position, noMove=False): if position == -1: @@ -791,7 +790,7 @@ class FileMethods(): self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder <= ? AND packageorder > ? AND queue=? AND packageorder >= 0', (position, p.order, p.queue)) self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (position, str(p.id))) - + @style.queue def reorderLink(self, f, position): """ reorder link with f as dict for pyfile """ @@ -801,34 +800,33 @@ class FileMethods(): self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder <= ? AND linkorder > ? AND package=?', (position, f["order"], f["package"])) self.c.execute('UPDATE links SET linkorder=? WHERE id=?', (position, f["id"])) - - + @style.queue def clearPackageOrder(self, p): self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (-1, str(p.id))) self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=? AND id != ?', (p.order, p.queue, str(p.id))) - + @style.async def restartFile(self, id): - self.c.execute('UPDATE links SET status=3,error="" WHERE id=?', (str(id),)) + self.c.execute('UPDATE links SET status=3, error="" WHERE id=?', (str(id),)) @style.async def restartPackage(self, id): self.c.execute('UPDATE links SET status=3 WHERE package=?', (str(id),)) - + @style.queue def getPackage(self, id): """return package instance from id""" - self.c.execute("SELECT name,folder,site,password,queue,packageorder FROM packages WHERE id=?", (str(id), )) + self.c.execute("SELECT name, folder, site, password, queue, packageorder FROM packages WHERE id=?", (str(id),)) r = self.c.fetchone() if not r: return None return PyPackage(self.manager, id, * r) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- @style.queue def getFile(self, id): """return link instance from id""" - self.c.execute("SELECT url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?", (str(id), )) + self.c.execute("SELECT url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?", (str(id),)) r = self.c.fetchone() if not r: return None return PyFile(self.manager, id, * r) @@ -845,11 +843,11 @@ class FileMethods(): for i, item in enumerate(occ): if i: cmd += ", " cmd += "'%s'" % item - + cmd += ")" - cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE ((p.queue=1 AND l.plugin NOT IN %s) OR l.plugin IN %s) AND l.status IN (2,3,14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % (cmd, pre) - + cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE ((p.queue=1 AND l.plugin NOT IN %s) OR l.plugin IN %s) AND l.status IN (2, 3, 14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % (cmd, pre) + self.c.execute(cmd) # very bad! return [x[0] for x in self.c] @@ -857,7 +855,7 @@ class FileMethods(): @style.queue def getPluginJob(self, plugins): """returns pyfile ids with suited plugins""" - cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE l.plugin IN %s AND l.status IN (2,3,14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % plugins + cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE l.plugin IN %s AND l.status IN (2, 3, 14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % plugins self.c.execute(cmd) # very bad! @@ -866,18 +864,18 @@ class FileMethods(): @style.queue def getUnfinished(self, pid): """return list of max length 3 ids with pyfiles in package not finished or processed""" - + self.c.execute("SELECT id FROM links WHERE package=? AND status NOT IN (0, 4, 13) LIMIT 3", (str(pid),)) return [r[0] for r in self.c] @style.queue def deleteFinished(self): - self.c.execute("DELETE FROM links WHERE status IN (0,4)") + self.c.execute("DELETE FROM links WHERE status IN (0, 4)") self.c.execute("DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE packages.id=links.package)") @style.queue def restartFailed(self): - self.c.execute("UPDATE links SET status=3,error='' WHERE status IN (6, 8, 9)") + self.c.execute("UPDATE links SET status=3, error='' WHERE status IN (6, 8, 9)") @style.queue def findDuplicates(self, id, folder, filename): @@ -891,54 +889,3 @@ class FileMethods(): self.c.execute("DELETE FROM packages;") DatabaseBackend.registerSub(FileMethods) - -if __name__ == "__main__": - - pypath = "." - _ = lambda x: x - - db = FileHandler(None) - - #p = PyFile(db, 5) - #sleep(0.1) - - a = time() - - #print db.addPackage("package", "folder" , 1) - - pack = db.db.addPackage("package", "folder", 1) - - updates = [] - - - for x in range(0, 200): - x = str(x) - db.db.addLink("http://somehost.com/hoster/file/download?file_id=" + x, x, "BasePlugin", pack) - updates.append(("new name" + x, 0, 3, "http://somehost.com/hoster/file/download?file_id=" + x)) - - - for x in range(0, 100): - updates.append(("unimportant%s" % x, 0, 3, "a really long non existent url%s" % x)) - - db.db.commit() - - b = time() - print "adding 200 links, single sql execs, no commit", b-a - - print db.getCompleteData(1) - - c = time() - - - db.db.updateLinkInfo(updates) - - d = time() - - print "updates", d-c - - print db.getCompleteData(1) - - - e = time() - - print "complete data", e-d diff --git a/module/database/StorageDatabase.py b/module/database/StorageDatabase.py index 3ed29625f..074d97d3e 100644 --- a/module/database/StorageDatabase.py +++ b/module/database/StorageDatabase.py @@ -19,7 +19,7 @@ from module.database import style from module.database import DatabaseBackend -class StorageMethods(): +class StorageMethods: @style.queue def setStorage(db, identifier, key, value): db.c.execute("SELECT id FROM storage WHERE identifier=? AND key=?", (identifier, key)) @@ -27,7 +27,7 @@ class StorageMethods(): db.c.execute("UPDATE storage SET value=? WHERE identifier=? AND key=?", (value, identifier, key)) else: db.c.execute("INSERT INTO storage (identifier, key, value) VALUES (?, ?, ?)", (identifier, key, value)) - + @style.queue def getStorage(db, identifier, key=None): if key is not None: @@ -36,12 +36,12 @@ class StorageMethods(): if row is not None: return row[0] else: - db.c.execute("SELECT key, value FROM storage WHERE identifier=?", (identifier, )) + db.c.execute("SELECT key, value FROM storage WHERE identifier=?", (identifier,)) d = {} for row in db.c: d[row[0]] = row[1] return d - + @style.queue def delStorage(db, identifier, key): db.c.execute("DELETE FROM storage WHERE identifier=? AND key=?", (identifier, key)) diff --git a/module/database/UserDatabase.py b/module/database/UserDatabase.py index 0c781057d..59b0f6dbf 100644 --- a/module/database/UserDatabase.py +++ b/module/database/UserDatabase.py @@ -22,11 +22,11 @@ import random from DatabaseBackend import DatabaseBackend from DatabaseBackend import style -class UserMethods(): +class UserMethods: @style.queue def checkAuth(db, user, password): c = db.c - c.execute('SELECT id, name, password, role, permission, template, email FROM "users" WHERE name=?', (user, )) + c.execute('SELECT id, name, password, role, permission, template, email FROM "users" WHERE name=?', (user,)) r = c.fetchone() if not r: return {} @@ -47,7 +47,7 @@ class UserMethods(): password = salt + h.hexdigest() c = db.c - c.execute('SELECT name FROM users WHERE name=?', (user, )) + c.execute('SELECT name FROM users WHERE name=?', (user,)) if c.fetchone() is not None: c.execute('UPDATE users SET password=? WHERE name=?', (password, user)) else: @@ -56,7 +56,7 @@ class UserMethods(): @style.queue def changePassword(db, user, oldpw, newpw): - db.c.execute('SELECT id, name, password FROM users WHERE name=?', (user, )) + db.c.execute('SELECT id, name, password FROM users WHERE name=?', (user,)) r = db.c.fetchone() if not r: return False @@ -103,6 +103,6 @@ class UserMethods(): @style.queue def removeUser(db, user): - db.c.execute('DELETE FROM users WHERE name=?', (user, )) + db.c.execute('DELETE FROM users WHERE name=?', (user,)) DatabaseBackend.registerSub(UserMethods) diff --git a/module/database/__init__.py b/module/database/__init__.py index 545789c0c..5f287a47f 100644 --- a/module/database/__init__.py +++ b/module/database/__init__.py @@ -1,6 +1,8 @@ +# -*- coding: utf-8 -*- + from DatabaseBackend import DatabaseBackend from DatabaseBackend import style from FileDatabase import FileHandler from UserDatabase import UserMethods -from StorageDatabase import StorageMethods
\ No newline at end of file +from StorageDatabase import StorageMethods diff --git a/module/debug.py b/module/debug.py index 8d1ddd3d0..54a159e78 100644 --- a/module/debug.py +++ b/module/debug.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python #coding:utf-8 import re @@ -41,7 +40,7 @@ def initReport(): reports.append(f) for i, f in enumerate(reports): - print "%s. %s" % (i,f) + print "%s. %s" % (i, f) choice = raw_input("Choose Report: ") @@ -92,4 +91,4 @@ def initReport(): return frame, plugin, pyfile if __name__=='__main__': - print "No main method, use this module with your python shell"
\ No newline at end of file + print "No main method, use this module with your python shell" diff --git a/module/forwarder.py b/module/forwarder.py index eacb33c2b..3cb3a7748 100644 --- a/module/forwarder.py +++ b/module/forwarder.py @@ -25,9 +25,9 @@ import thread from traceback import print_exc -class Forwarder(): +class Forwarder: - def __init__(self, extip,extport=9666): + def __init__(self, extip, extport=9666): print "Start portforwarding to %s:%s" % (extip, extport) proxy(extip, extport, 9666) @@ -49,8 +49,7 @@ def server(*settings): thread.start_new_thread(forward, (server_socket, client_socket)) except Exception: print_exc() - - + def forward(source, destination): string = ' ' while string: @@ -60,14 +59,3 @@ def forward(source, destination): else: #source.shutdown(socket.SHUT_RD) destination.shutdown(socket.SHUT_WR) - -if __name__ == "__main__": - args = argv[1:] - if not args: - print "Usage: forwarder.py <remote ip> <remote port>" - exit() - if len(args) == 1: - args.append(9666) - - f = Forwarder(args[0], int(args[1])) -
\ No newline at end of file diff --git a/module/gui/AccountEdit.py b/module/gui/AccountEdit.py deleted file mode 100644 index b22cfc49f..000000000 --- a/module/gui/AccountEdit.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from os.path import join - -class AccountEdit(QWidget): - """ - account editor widget - """ - - def __init__(self): - QMainWindow.__init__(self) - - self.setWindowTitle(_("Edit account")) - self.setWindowIcon(QIcon(join(pypath, "icons","logo.png"))) - - self.setLayout(QGridLayout()) - l = self.layout() - - typeLabel = QLabel(_("Type")) - loginLabel = QLabel(_("Login")) - passwordLabel = QLabel(_("New password")) - changePw = QCheckBox() - changePw.setChecked(False) - self.changePw = changePw - password = QLineEdit() - password.setEnabled(False) - password.setEchoMode(QLineEdit.Password) - self.password = password - login = QLineEdit() - self.login = login - acctype = QComboBox() - self.acctype = acctype - - save = QPushButton(_("Save")) - - self.connect(changePw, SIGNAL("toggled(bool)"), password, SLOT("setEnabled(bool)")) - - l.addWidget(save, 3, 0, 1, 3) - l.addWidget(acctype, 0, 1, 1, 2) - l.addWidget(login, 1, 1, 1, 2) - l.addWidget(password, 2, 2) - l.addWidget(changePw, 2, 1) - l.addWidget(passwordLabel, 2, 0) - l.addWidget(loginLabel, 1, 0) - l.addWidget(typeLabel, 0, 0) - - self.connect(save, SIGNAL("clicked()"), self.slotSave) - - def slotSave(self): - """ - save entered data - """ - data = {"login": str(self.login.text()), "acctype": str(self.acctype.currentText()), "password": False} - if self.changePw.isChecked(): - data["password"] = str(self.password.text()) - self.emit(SIGNAL("done"), data) - - @staticmethod - def newAccount(types): - """ - create empty editor instance - """ - w = AccountEdit() - w.setWindowTitle(_("Create account")) - - w.changePw.setChecked(True) - w.password.setEnabled(True) - - w.acctype.addItems(types) - - return w - - @staticmethod - def editAccount(types, base): - """ - create editor instance with given data - """ - w = AccountEdit() - - w.acctype.addItems(types) - w.acctype.setCurrentIndex(types.index(base["type"])) - - w.login.setText(base["login"]) - - return w diff --git a/module/gui/Accounts.py b/module/gui/Accounts.py deleted file mode 100644 index 8db04dfa9..000000000 --- a/module/gui/Accounts.py +++ /dev/null @@ -1,213 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from time import strftime, gmtime - -class AccountModel(QAbstractItemModel): - """ - model for account view - """ - - def __init__(self, view, connector): - QAbstractItemModel.__init__(self) - self.connector = connector - self.view = view - self._data = [] - self.cols = 4 - self.mutex = QMutex() - - def reloadData(self, force=False): - """ - reload account list - """ - accounts = self.connector.proxy.getAccounts(False) - - if self._data == accounts: - return - - if len(self._data) > 0: - self.beginRemoveRows(QModelIndex(), 0, len(self._data)-1) - self._data = [] - self.endRemoveRows() - - if len(accounts) > 0: - self.beginInsertRows(QModelIndex(), 0, len(accounts)-1) - self._data = accounts - self.endInsertRows() - - def toData(self, index): - """ - return index pointer - """ - return index.internalPointer() - - def data(self, index, role=Qt.DisplayRole): - """ - return cell data - """ - if not index.isValid(): - return QVariant() - if role == Qt.DisplayRole: - if index.column() == 0: - return QVariant(self.toData(index).type) - elif index.column() == 1: - return QVariant(self.toData(index).login) - elif index.column() == 2: - if not self.toData(index).valid: - return QVariant(_("not valid")) - if not self.toData(index).validuntil: - return QVariant(_("n/a")) - until = int(self.toData(index).validuntil) - if until > 0: - fmtime = strftime(_("%a, %d %b %Y %H:%M"), gmtime(until)) - return QVariant(fmtime) - else: - return QVariant(_("unlimited")) - #elif role == Qt.EditRole: - # if index.column() == 0: - # return QVariant(index.internalPointer().data["name"]) - return QVariant() - - def index(self, row, column, parent=QModelIndex()): - """ - create index with data pointer - """ - if parent == QModelIndex() and len(self._data) > row: - pointer = self._data[row] - index = self.createIndex(row, column, pointer) - elif parent.isValid(): - pointer = parent.internalPointer().children[row] - index = self.createIndex(row, column, pointer) - else: - index = QModelIndex() - return index - - def parent(self, index): - """ - no parents, everything on top level - """ - return QModelIndex() - - def rowCount(self, parent=QModelIndex()): - """ - account count - """ - if parent == QModelIndex(): - return len(self._data) - return 0 - - def columnCount(self, parent=QModelIndex()): - return self.cols - - def hasChildren(self, parent=QModelIndex()): - """ - everything on top level - """ - if parent == QModelIndex(): - return True - else: - return False - - def canFetchMore(self, parent): - return False - - def headerData(self, section, orientation, role=Qt.DisplayRole): - """ - returns column heading - """ - if orientation == Qt.Horizontal and role == Qt.DisplayRole: - if section == 0: - return QVariant(_("Type")) - elif section == 1: - return QVariant(_("Login")) - elif section == 2: - return QVariant(_("Valid until")) - elif section == 3: - return QVariant(_("Traffic left")) - return QVariant() - - def flags(self, index): - """ - cell flags - """ - return Qt.ItemIsSelectable | Qt.ItemIsEnabled - -class AccountView(QTreeView): - """ - view component for accounts - """ - - def __init__(self, connector): - QTreeView.__init__(self) - self.setModel(AccountModel(self, connector)) - - self.setColumnWidth(0, 150) - self.setColumnWidth(1, 150) - self.setColumnWidth(2, 150) - self.setColumnWidth(3, 150) - - self.setEditTriggers(QAbstractItemView.NoEditTriggers) - - self.delegate = AccountDelegate(self, self.model()) - self.setItemDelegateForColumn(3, self.delegate) - -class AccountDelegate(QItemDelegate): - """ - used to display a progressbar for the traffic in the traffic cell - """ - - def __init__(self, parent, model): - QItemDelegate.__init__(self, parent) - self.model = model - - def paint(self, painter, option, index): - """ - paint the progressbar - """ - if not index.isValid(): - return - if index.column() == 3: - data = self.model.toData(index) - opts = QStyleOptionProgressBarV2() - opts.minimum = 0 - if data.trafficleft: - if data.trafficleft == -1 or data.trafficleft is None: - opts.maximum = opts.progress = 1 - else: - opts.maximum = opts.progress = data.trafficleft - if data.maxtraffic: - opts.maximum = data.maxtraffic - - opts.rect = option.rect - opts.rect.setRight(option.rect.right()-1) - opts.rect.setHeight(option.rect.height()-1) - opts.textVisible = True - opts.textAlignment = Qt.AlignCenter - if data.trafficleft and data.trafficleft == -1: - opts.text = QString(_("unlimited")) - elif data.trafficleft is None: - opts.text = QString(_("n/a")) - else: - opts.text = QString.number(round(float(opts.progress)/1024/1024, 2)) + " GB" - QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter) - return - QItemDelegate.paint(self, painter, option, index) - diff --git a/module/gui/CNLServer.py b/module/gui/CNLServer.py deleted file mode 100644 index 5ecac8277..000000000 --- a/module/gui/CNLServer.py +++ /dev/null @@ -1,226 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: RaNaN -""" -import re -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -from threading import Thread -from cgi import FieldStorage -from os.path import abspath, dirname, join -from urllib import unquote -from base64 import standard_b64decode -from binascii import unhexlify - -try: - from Crypto.Cipher import AES -except: - pass - -try: - from module.common import JsEngine -except ImportError: - import sys - sys.path.append(join(abspath(dirname(__file__)), "..", "..")) - from module.common import JsEngine - -js = JsEngine.JsEngine() -core = None - -class CNLServer(Thread): - def __init__(self): - Thread.__init__(self) - self.setDaemon(True) - - self.stop = False - self.stopped = False - - def run(self): - server_address = ('127.0.0.1', 9666) - try: - httpd = HTTPServer(server_address, CNLHandler) - except: - self.stopped = True - return - - self.stopped = False - while self.keep_running(): - httpd.handle_request() - self.stopped = True - - def keep_running(self): - return not self.stop - - -class CNLHandler(BaseHTTPRequestHandler): - - #def log_message(self, *args): - # pass - - def add_package(self, name, urls, queue=0): - print "name", name - print "urls", urls - print "queue", queue - - def get_post(self, name, default=""): - if name in self.post: - return self.post[name] - else: - return default - - def start_response(self, string): - - self.send_response(200) - - self.send_header("Content-Length", len(string)) - self.send_header("Content-Language", "de") - self.send_header("Vary", "Accept-Language, Cookie") - self.send_header("Cache-Control", "no-cache, must-revalidate") - self.send_header("Content-type", "text/html") - self.end_headers() - - def do_GET(self): - path = self.path.strip("/").lower() - #self.wfile.write(path+"\n") - - self.map = [ (r"add$", self.add), - (r"addcrypted$", self.addcrypted), - (r"addcrypted2$", self.addcrypted2), - (r"flashgot", self.flashgot), - (r"crossdomain\.xml", self.crossdomain), - (r"checkSupportForUrl", self.checksupport), - (r"jdcheck.js", self.jdcheck), - (r"", self.flash) ] - - func = None - for r, f in self.map: - if re.match(r"(flash(got)?/?)?"+r, path): - func = f - break - - if func: - try: - resp = func() - if not resp: resp = "success" - resp += "\r\n" - self.start_response(resp) - self.wfile.write(resp) - except Exception,e : - self.send_error(500, str(e)) - else: - self.send_error(404, "Not Found") - - def do_POST(self): - form = FieldStorage( - fp=self.rfile, - headers=self.headers, - environ={'REQUEST_METHOD':'POST', - 'CONTENT_TYPE':self.headers['Content-Type'], - }) - - self.post = {} - for name in form.keys(): - self.post[name] = form[name].value - - return self.do_GET() - - def flash(self): - return "JDownloader" - - def add(self): - package = self.get_post('referer', 'ClickAndLoad Package') - urls = filter(lambda x: x != "", self.get_post('urls').split("\n")) - - self.add_package(package, urls, 0) - - def addcrypted(self): - package = self.get_post('referer', 'ClickAndLoad Package') - dlc = self.get_post('crypted').replace(" ", "+") - - core.upload_container(package, dlc) - - def addcrypted2(self): - package = self.get_post("source", "ClickAndLoad Package") - crypted = self.get_post("crypted") - jk = self.get_post("jk") - - crypted = standard_b64decode(unquote(crypted.replace(" ", "+"))) - jk = "%s f()" % jk - jk = js.eval(jk) - Key = unhexlify(jk) - IV = Key - - obj = AES.new(Key, AES.MODE_CBC, IV) - result = obj.decrypt(crypted).replace("\x00", "").replace("\r","").split("\n") - - result = filter(lambda x: x != "", result) - - self.add_package(package, result, 0) - - - def flashgot(self): - autostart = int(self.get_post('autostart', 0)) - package = self.get_post('package', "FlashGot") - urls = filter(lambda x: x != "", self.get_post('urls').split("\n")) - - self.add_package(package, urls, autostart) - - def crossdomain(self): - rep = "<?xml version=\"1.0\"?>\n" - rep += "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n" - rep += "<cross-domain-policy>\n" - rep += "<allow-access-from domain=\"*\" />\n" - rep += "</cross-domain-policy>" - return rep - - def checksupport(self): - pass - - def jdcheck(self): - rep = "jdownloader=true;\n" - rep += "var version='10629';\n" - return rep - - -if __name__ == "__main__": - import xmlrpclib - from module import InitHomeDir - from module.ConfigParser import ConfigParser - - config = ConfigParser() - - ssl = "" - if config.get("ssl", "activated"): - ssl = "s" - - server_url = "http%s://%s:%s@%s:%s/" % ( - ssl, - config.username, - config.password, - config.get("remote", "listenaddr"), - config.get("remote", "port") - ) - - core = xmlrpclib.ServerProxy(server_url, allow_none=True) - - s = CNLServer() - s.start() - while not s.stopped: - try: - s.join(1) - except KeyboardInterrupt: - s.stop = True - s.stopped = True - print "quiting.." diff --git a/module/gui/CaptchaDock.py b/module/gui/CaptchaDock.py deleted file mode 100644 index b88cb53ca..000000000 --- a/module/gui/CaptchaDock.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -class CaptchaDock(QDockWidget): - """ - dock widget for captcha input - """ - - def __init__(self): - QDockWidget.__init__(self, _("Captcha")) - self.setObjectName("Captcha Dock") - self.widget = CaptchaDockWidget(self) - self.setWidget(self.widget) - self.setAllowedAreas(Qt.BottomDockWidgetArea) - self.setFeatures(QDockWidget.NoDockWidgetFeatures) - self.hide() - self.processing = False - self.currentID = None - self.connect(self, SIGNAL("setTask"), self.setTask) - - def isFree(self): - return not self.processing - - def setTask(self, tid, img, imgType): - self.processing = True - data = QByteArray(img) - self.currentID = tid - self.widget.emit(SIGNAL("setImage"), data) - self.widget.input.setText("") - self.show() - -class CaptchaDockWidget(QWidget): - """ - widget for the input widgets - """ - - def __init__(self, dock): - QWidget.__init__(self) - self.dock = dock - self.setLayout(QHBoxLayout()) - layout = self.layout() - - imgLabel = QLabel() - captchaInput = QLineEdit() - okayButton = QPushButton(_("OK")) - cancelButton = QPushButton(_("Cancel")) - - layout.addStretch() - layout.addWidget(imgLabel) - layout.addWidget(captchaInput) - layout.addWidget(okayButton) - layout.addWidget(cancelButton) - layout.addStretch() - - self.input = captchaInput - - self.connect(okayButton, SIGNAL("clicked()"), self.slotSubmit) - self.connect(captchaInput, SIGNAL("returnPressed()"), self.slotSubmit) - self.connect(self, SIGNAL("setImage"), self.setImg) - self.connect(self, SIGNAL("setPixmap(const QPixmap &)"), imgLabel, SLOT("setPixmap(const QPixmap &)")) - - def setImg(self, data): - pixmap = QPixmap() - pixmap.loadFromData(data) - self.emit(SIGNAL("setPixmap(const QPixmap &)"), pixmap) - self.input.setFocus(Qt.OtherFocusReason) - - def slotSubmit(self): - text = self.input.text() - tid = self.dock.currentID - self.dock.currentID = None - self.dock.emit(SIGNAL("done"), tid, str(text)) - self.dock.hide() - self.dock.processing = False - diff --git a/module/gui/Collector.py b/module/gui/Collector.py deleted file mode 100644 index 3ec4262f1..000000000 --- a/module/gui/Collector.py +++ /dev/null @@ -1,407 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from module.PyFile import statusMap -from module.utils import formatSize - -from module.remote.thriftbackend.ThriftClient import Destination, FileDoesNotExists, ElementType - -statusMapReverse = dict((v,k) for k, v in statusMap.iteritems()) - -translatedStatusMap = {} # -> CollectorModel.__init__ - -class CollectorModel(QAbstractItemModel): - """ - model for the collector view - """ - - def __init__(self, view, connector): - QAbstractItemModel.__init__(self) - self.connector = connector - self.view = view - self._data = [] - self.cols = 4 - self.interval = 1 - self.mutex = QMutex() - - global translatedStatusMap # workaround because i18n is not running at import time - translatedStatusMap = { - "finished": _("finished"), - "offline": _("offline"), - "online": _("online"), - "queued": _("queued"), - "skipped": _("skipped"), - "waiting": _("waiting"), - "temp. offline": _("temp. offline"), - "starting": _("starting"), - "failed": _("failed"), - "aborted": _("aborted"), - "decrypting": _("decrypting"), - "custom": _("custom"), - "downloading": _("downloading"), - "processing": _("processing") - } - - def translateStatus(self, string): - """ - used to convert to locale specific status - """ - return translatedStatusMap[string] - - def addEvent(self, event): - """ - called from main loop, pass events to the correct methods - """ - QMutexLocker(self.mutex) - if event.eventname == "reload": - self.fullReload() - elif event.eventname == "remove": - self.removeEvent(event) - elif event.eventname == "insert": - self.insertEvent(event) - elif event.eventname == "update": - self.updateEvent(event) - - def fullReload(self): - """ - reload whole model, used at startup to load initial data - """ - self._data = [] - order = self.connector.getPackageOrder(Destination.Collector) - self.beginInsertRows(QModelIndex(), 0, len(order.values())) - for position, pid in order.iteritems(): - pack = self.connector.getPackageData(pid) - package = Package(pack) - self._data.append(package) - self._data = sorted(self._data, key=lambda p: p.data["order"]) - self.endInsertRows() - - def removeEvent(self, event): - """ - remove an element from model - """ - if event.type == ElementType.File: - for p, package in enumerate(self._data): - for k, child in enumerate(package.children): - if child.id == event.id: - self.beginRemoveRows(self.index(p, 0), k, k) - del package.children[k] - self.endRemoveRows() - break - else: - for k, package in enumerate(self._data): - if package.id == event.id: - self.beginRemoveRows(QModelIndex(), k, k) - del self._data[k] - self.endRemoveRows() - break - - def insertEvent(self, event): - """ - inserts a new element in the model - """ - if event.type == ElementType.File: - try: - info = self.connector.getFileData(event.id) - except FileDoesNotExists: - return - - for k, package in enumerate(self._data): - if package.id == info.package: - if package.getChild(info.fid): - self.updateEvent(event) - break - self.beginInsertRows(self.index(k, 0), info.order, info.order) - package.addChild(info) - self.endInsertRows() - break - else: - data = self.connector.getPackageData(event.id) - package = Package(data) - self.beginInsertRows(QModelIndex(), data.order, data.order) - self._data.insert(data.order, package) - self.endInsertRows() - - def updateEvent(self, event): - """ - update an element in the model - """ - if event.type == ElementType.File: - try: - info = self.connector.proxy.getFileData(event.id) - except FileDoesNotExists: - return - for p, package in enumerate(self._data): - if package.id == info.packageID: - for k, child in enumerate(package.children): - if child.id == event.id: - child.update(info) - if not info.status == 12: - child.data["downloading"] = None - self.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), self.index(k, 0, self.index(p, 0)), self.index(k, self.cols, self.index(p, self.cols))) - break - else: - data = self.connector.getPackageData(event.id) - if not data: - return - for p, package in enumerate(self._data): - if package.id == event.id: - package.update(data) - self.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), self.index(p, 0), self.index(p, self.cols)) - break - - def data(self, index, role=Qt.DisplayRole): - """ - return cell data - """ - if not index.isValid(): - return QVariant() - if role == Qt.DisplayRole: - if index.column() == 0: - return QVariant(index.internalPointer().data["name"]) - elif index.column() == 1: - item = index.internalPointer() - plugins = [] - if isinstance(item, Package): - for child in item.children: - if not child.data["plugin"] in plugins: - plugins.append(child.data["plugin"]) - else: - plugins.append(item.data["plugin"]) - return QVariant(", ".join(plugins)) - elif index.column() == 2: - item = index.internalPointer() - status = 0 - if isinstance(item, Package): - for child in item.children: - if child.data["status"] > status: - status = child.data["status"] - else: - status = item.data["status"] - return QVariant(self.translateStatus(statusMapReverse[status])) - elif index.column() == 3: - item = index.internalPointer() - if isinstance(item, Link): - return QVariant(formatSize(item.data["size"])) - else: - ms = 0 - for c in item.children: - ms += c.data["size"] - return QVariant(formatSize(ms)) - elif role == Qt.EditRole: - if index.column() == 0: - return QVariant(index.internalPointer().data["name"]) - return QVariant() - - def index(self, row, column, parent=QModelIndex()): - """ - creates a cell index with pointer to the data - """ - if parent == QModelIndex() and len(self._data) > row: - pointer = self._data[row] - index = self.createIndex(row, column, pointer) - elif parent.isValid(): - try: - pointer = parent.internalPointer().children[row] - except: - return QModelIndex() - index = self.createIndex(row, column, pointer) - else: - index = QModelIndex() - return index - - def parent(self, index): - """ - return index of parent element - only valid for links - """ - if index == QModelIndex(): - return QModelIndex() - if index.isValid(): - link = index.internalPointer() - if isinstance(link, Link): - for k, pack in enumerate(self._data): - if pack == link.package: - return self.createIndex(k, 0, link.package) - return QModelIndex() - - def rowCount(self, parent=QModelIndex()): - """ - returns row count for the element - """ - if parent == QModelIndex(): - #return package count - return len(self._data) - else: - if parent.isValid(): - #index is valid - pack = parent.internalPointer() - if isinstance(pack, Package): - #index points to a package - #return len of children - return len(pack.children) - else: - #index is invalid - return False - #files have no children - return 0 - - def columnCount(self, parent=QModelIndex()): - return self.cols - - def hasChildren(self, parent=QModelIndex()): - if not parent.isValid(): - return True - return self.rowCount(parent) > 0 - - def canFetchMore(self, parent): - return False - - def headerData(self, section, orientation, role=Qt.DisplayRole): - """ - returns column heading - """ - if orientation == Qt.Horizontal and role == Qt.DisplayRole: - if section == 0: - return QVariant(_("Name")) - elif section == 1: - return QVariant(_("Plugin")) - elif section == 2: - return QVariant(_("Status")) - elif section == 3: - return QVariant(_("Size")) - return QVariant() - - def flags(self, index): - """ - cell flags - """ - if index.column() == 0 and self.parent(index) == QModelIndex(): - return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled - return Qt.ItemIsSelectable | Qt.ItemIsEnabled - - def setData(self, index, value, role=Qt.EditRole): - """ - called if package name editing is finished, sets new name - """ - if index.column() == 0 and self.parent(index) == QModelIndex() and role == Qt.EditRole: - self.connector.setPackageName(index.internalPointer().id, str(value.toString())) - return True - -class Package(object): - """ - package object in the model - """ - - def __init__(self, pack): - self.id = pack.pid - self.children = [] - for f in pack.links: - self.addChild(f) - self.data = {} - self.update(pack) - - def update(self, pack): - """ - update data dict from thift object - """ - data = { - "name": pack.name, - "folder": pack.folder, - "site": pack.site, - "password": pack.password, - "order": pack.order, - } - self.data.update(data) - - def addChild(self, f): - """ - add child (Link) to package - """ - self.children.insert(f.order, Link(f, self)) - self.children = sorted(self.children, key=lambda l: l.data["order"]) - - def getChild(self, fid): - """ - get child from package - """ - for child in self.children: - if child.id == int(fid): - return child - return None - - def getChildKey(self, fid): - """ - get child index - """ - for k, child in enumerate(self.children): - if child.id == int(fid): - return k - return None - - def removeChild(self, fid): - """ - remove child - """ - for k, child in enumerate(self.children): - if child.id == int(fid): - del self.children[k] - -class Link(object): - def __init__(self, f, pack): - self.data = {"downloading": None} - self.update(f) - self.id = f.fid - self.package = pack - - def update(self, f): - """ - update data dict from thift object - """ - data = { - "url": f.url, - "name": f.name, - "plugin": f.plugin, - "size": f.size, - "format_size": f.format_size, - "status": f.status, - "statusmsg": f.statusmsg, - "package": f.packageID, - "error": f.error, - "order": f.order, - } - self.data.update(data) - -class CollectorView(QTreeView): - """ - view component for collector - """ - - def __init__(self, connector): - QTreeView.__init__(self) - self.setModel(CollectorModel(self, connector)) - self.setColumnWidth(0, 500) - self.setColumnWidth(1, 100) - self.setColumnWidth(2, 200) - self.setColumnWidth(3, 100) - - self.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed) - diff --git a/module/gui/ConnectionManager.py b/module/gui/ConnectionManager.py deleted file mode 100644 index def575abc..000000000 --- a/module/gui/ConnectionManager.py +++ /dev/null @@ -1,302 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from os.path import join - -from uuid import uuid4 as uuid - -class ConnectionManager(QWidget): - - - warningShown = False - - def __init__(self): - QWidget.__init__(self) - - if not self.warningShown: - QMessageBox.warning(self, 'Warning', - "We are sorry but the GUI is not stable yet. Please use the webinterface for much better experience. \n", QMessageBox.Ok) - ConnectionManager.warningShown = True - - mainLayout = QHBoxLayout() - buttonLayout = QVBoxLayout() - - self.setWindowTitle(_("pyLoad ConnectionManager")) - self.setWindowIcon(QIcon(join(pypath, "icons","logo.png"))) - - connList = QListWidget() - - new = QPushButton(_("New")) - edit = QPushButton(_("Edit")) - remove = QPushButton(_("Remove")) - connect = QPushButton(_("Connect")) - - #box = QFrame() - boxLayout = QVBoxLayout() - #box.setLayout(boxLayout) - - boxLayout.addWidget(QLabel(_("Connect:"))) - boxLayout.addWidget(connList) - - line = QFrame() - #line.setFixedWidth(100) - line.setFrameShape(line.HLine) - line.setFrameShadow(line.Sunken) - line.setFixedHeight(10) - - boxLayout.addWidget(line) - - form = QFormLayout() - form.setMargin(5) - form.setSpacing(20) - - form.setAlignment(Qt.AlignRight) - checkbox = QCheckBox() - form.addRow(_("Use internal Core:"), checkbox) - - boxLayout.addLayout(form) - - mainLayout.addLayout(boxLayout) - mainLayout.addLayout(buttonLayout) - - buttonLayout.addWidget(new) - buttonLayout.addWidget(edit) - buttonLayout.addWidget(remove) - buttonLayout.addStretch() - buttonLayout.addWidget(connect) - - self.setLayout(mainLayout) - - self.internal = checkbox - self.new = new - self.connectb = connect - self.remove = remove - self.editb = edit - self.connList = connList - self.edit = self.EditWindow() - self.connectSignals() - - self.defaultStates = {} - - def connectSignals(self): - self.connect(self, SIGNAL("setConnections"), self.setConnections) - self.connect(self.new, SIGNAL("clicked()"), self.slotNew) - self.connect(self.editb, SIGNAL("clicked()"), self.slotEdit) - self.connect(self.remove, SIGNAL("clicked()"), self.slotRemove) - self.connect(self.connectb, SIGNAL("clicked()"), self.slotConnect) - self.connect(self.edit, SIGNAL("save"), self.slotSave) - self.connect(self.connList, SIGNAL("itemDoubleClicked(QListWidgetItem *)"), self.slotItemDoubleClicked) - self.connect(self.internal, SIGNAL("clicked()"), self.slotInternal) - - def setConnections(self, connections): - self.connList.clear() - for conn in connections: - item = QListWidgetItem() - item.setData(Qt.DisplayRole, QVariant(conn["name"])) - item.setData(Qt.UserRole, QVariant(conn)) - self.connList.addItem(item) - if conn["default"]: - item.setData(Qt.DisplayRole, QVariant(_("%s (Default)") % conn["name"])) - self.connList.setCurrentItem(item) - - def slotNew(self): - data = {"id":uuid().hex, "type":"remote", "default":False, "name":"", "host":"", "port":"7228", "user":"admin", "password":""} - self.edit.setData(data) - self.edit.show() - - def slotEdit(self): - item = self.connList.currentItem() - data = item.data(Qt.UserRole).toPyObject() - data = self.cleanDict(data) - self.edit.setData(data) - self.edit.show() - - def slotRemove(self): - item = self.connList.currentItem() - data = item.data(Qt.UserRole).toPyObject() - data = self.cleanDict(data) - self.emit(SIGNAL("removeConnection"), data) - - def slotConnect(self): - if self.internal.checkState() == 2: - data = {"type": "internal"} - self.emit(SIGNAL("connect"), data) - else: - item = self.connList.currentItem() - data = item.data(Qt.UserRole).toPyObject() - data = self.cleanDict(data) - self.emit(SIGNAL("connect"), data) - - def cleanDict(self, data): - tmp = {} - for k, d in data.items(): - tmp[str(k)] = d - return tmp - - def slotSave(self, data): - self.emit(SIGNAL("saveConnection"), data) - - def slotItemDoubleClicked(self, defaultItem): - data = defaultItem.data(Qt.UserRole).toPyObject() - self.setDefault(data, True) - did = self.cleanDict(data)["id"] - #allItems = self.connList.findItems("*", Qt.MatchWildcard) - count = self.connList.count() - for i in range(count): - item = self.connList.item(i) - data = item.data(Qt.UserRole).toPyObject() - if self.cleanDict(data)["id"] == did: - continue - self.setDefault(data, False) - - def slotInternal(self): - if self.internal.checkState() == 2: - self.connList.clearSelection() - - def setDefault(self, data, state): - data = self.cleanDict(data) - self.edit.setData(data) - data = self.edit.getData() - data["default"] = state - self.edit.emit(SIGNAL("save"), data) - - class EditWindow(QWidget): - def __init__(self): - QWidget.__init__(self) - - self.setWindowTitle(_("pyLoad ConnectionManager")) - self.setWindowIcon(QIcon(join(pypath, "icons","logo.png"))) - - grid = QGridLayout() - - nameLabel = QLabel(_("Name:")) - hostLabel = QLabel(_("Host:")) - localLabel = QLabel(_("Local:")) - userLabel = QLabel(_("User:")) - pwLabel = QLabel(_("Password:")) - portLabel = QLabel(_("Port:")) - - name = QLineEdit() - host = QLineEdit() - local = QCheckBox() - user = QLineEdit() - password = QLineEdit() - password.setEchoMode(QLineEdit.Password) - port = QSpinBox() - port.setRange(1,10000) - - save = QPushButton(_("Save")) - cancel = QPushButton(_("Cancel")) - - grid.addWidget(nameLabel, 0, 0) - grid.addWidget(name, 0, 1) - grid.addWidget(localLabel, 1, 0) - grid.addWidget(local, 1, 1) - grid.addWidget(hostLabel, 2, 0) - grid.addWidget(host, 2, 1) - grid.addWidget(portLabel, 3, 0) - grid.addWidget(port, 3, 1) - grid.addWidget(userLabel, 4, 0) - grid.addWidget(user, 4, 1) - grid.addWidget(pwLabel, 5, 0) - grid.addWidget(password, 5, 1) - grid.addWidget(cancel, 6, 0) - grid.addWidget(save, 6, 1) - - self.setLayout(grid) - self.controls = {"name": name, - "host": host, - "local": local, - "user": user, - "password": password, - "port": port, - "save": save, - "cancel": cancel} - - self.connect(cancel, SIGNAL("clicked()"), self.hide) - self.connect(save, SIGNAL("clicked()"), self.slotDone) - self.connect(local, SIGNAL("stateChanged(int)"), self.slotLocalChanged) - - self.id = None - self.default = None - - def setData(self, data): - if not data: return - - self.id = data["id"] - self.default = data["default"] - self.controls["name"].setText(data["name"]) - if data["type"] == "local": - data["local"] = True - else: - data["local"] = False - self.controls["local"].setChecked(data["local"]) - if not data["local"]: - self.controls["user"].setText(data["user"]) - self.controls["password"].setText(data["password"]) - self.controls["port"].setValue(int(data["port"])) - self.controls["host"].setText(data["host"]) - self.controls["user"].setDisabled(False) - self.controls["password"].setDisabled(False) - self.controls["port"].setDisabled(False) - self.controls["host"].setDisabled(False) - else: - self.controls["user"].setText("") - self.controls["port"].setValue(1) - self.controls["host"].setText("") - self.controls["user"].setDisabled(True) - self.controls["password"].setDisabled(True) - self.controls["port"].setDisabled(True) - self.controls["host"].setDisabled(True) - - def slotLocalChanged(self, val): - if val == 2: - self.controls["user"].setDisabled(True) - self.controls["password"].setDisabled(True) - self.controls["port"].setDisabled(True) - self.controls["host"].setDisabled(True) - elif val == 0: - self.controls["user"].setDisabled(False) - self.controls["password"].setDisabled(False) - self.controls["port"].setDisabled(False) - self.controls["host"].setDisabled(False) - - def getData(self): - d = {} - d["id"] = self.id - d["default"] = self.default - d["name"] = self.controls["name"].text() - d["local"] = self.controls["local"].isChecked() - d["user"] = self.controls["user"].text() - d["password"] = self.controls["password"].text() - d["host"] = self.controls["host"].text() - d["port"] = self.controls["port"].value() - if d["local"]: - d["type"] = "local" - else: - d["type"] = "remote" - return d - - def slotDone(self): - data = self.getData() - self.hide() - self.emit(SIGNAL("save"), data) - diff --git a/module/gui/CoreConfigParser.py b/module/gui/CoreConfigParser.py deleted file mode 100644 index 0d1d298c6..000000000 --- a/module/gui/CoreConfigParser.py +++ /dev/null @@ -1,165 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement -from os.path import exists -from os.path import join - - -CONF_VERSION = 1 - -######################################################################## -class ConfigParser: - - #---------------------------------------------------------------------- - def __init__(self, configdir): - """Constructor""" - self.configdir = configdir - self.config = {} - - if self.checkVersion(): - self.readConfig() - - #---------------------------------------------------------------------- - def checkVersion(self): - - if not exists(join(self.configdir, "pyload.conf")): - return False - f = open(join(self.configdir, "pyload.conf"), "rb") - v = f.readline() - f.close() - v = v[v.find(":")+1:].strip() - - if int(v) < CONF_VERSION: - return False - - return True - - #---------------------------------------------------------------------- - def readConfig(self): - """reads the config file""" - - self.config = self.parseConfig(join(self.configdir, "pyload.conf")) - - - #---------------------------------------------------------------------- - def parseConfig(self, config): - """parses a given configfile""" - - f = open(config) - - config = f.read() - - config = config.split("\n")[1:] - - conf = {} - - section, option, value, typ, desc = "","","","","" - - listmode = False - - for line in config: - - line = line.rpartition("#") # removes comments - - if line[1]: - line = line[0] - else: - line = line[2] - - line = line.strip() - - try: - - if line == "": - continue - elif line.endswith(":"): - section, none, desc = line[:-1].partition('-') - section = section.strip() - desc = desc.replace('"', "").strip() - conf[section] = { "desc" : desc } - else: - if listmode: - - if line.endswith("]"): - listmode = False - line = line.replace("]","") - - value += [self.cast(typ, x.strip()) for x in line.split(",") if x] - - if not listmode: - conf[section][option] = { "desc" : desc, - "type" : typ, - "value" : value} - - - else: - content, none, value = line.partition("=") - - content, none, desc = content.partition(":") - - desc = desc.replace('"', "").strip() - - typ, option = content.split() - - value = value.strip() - - if value.startswith("["): - if value.endswith("]"): - listmode = False - value = value[:-1] - else: - listmode = True - - value = [self.cast(typ, x.strip()) for x in value[1:].split(",") if x] - else: - value = self.cast(typ, value) - - if not listmode: - conf[section][option] = { "desc" : desc, - "type" : typ, - "value" : value} - - except: - pass - - - f.close() - return conf - - #---------------------------------------------------------------------- - def cast(self, typ, value): - """cast value to given format""" - if type(value) not in (str, unicode): - return value - - if typ == "int": - return int(value) - elif typ == "bool": - return True if value.lower() in ("1","true", "on", "an","yes") else False - else: - return value - - #---------------------------------------------------------------------- - def get(self, section, option): - """get value""" - return self.config[section][option]["value"] - - #---------------------------------------------------------------------- - def __getitem__(self, section): - """provides dictonary like access: c['section']['option']""" - return Section(self, section) - -######################################################################## -class Section: - """provides dictionary like access for configparser""" - - #---------------------------------------------------------------------- - def __init__(self, parser, section): - """Constructor""" - self.parser = parser - self.section = section - - #---------------------------------------------------------------------- - def __getitem__(self, item): - """getitem""" - return self.parser.get(self.section, item) diff --git a/module/gui/LinkDock.py b/module/gui/LinkDock.py deleted file mode 100644 index ac2d4aae5..000000000 --- a/module/gui/LinkDock.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -class NewLinkDock(QDockWidget): - def __init__(self): - QDockWidget.__init__(self, "New Links") - self.setObjectName("New Links Dock") - self.widget = NewLinkWindow(self) - self.setWidget(self.widget) - self.setAllowedAreas(Qt.RightDockWidgetArea|Qt.LeftDockWidgetArea) - self.hide() - - def slotDone(self): - text = str(self.widget.box.toPlainText()) - lines = text.splitlines() - self.emit(SIGNAL("done"), lines) - self.widget.box.clear() - self.hide() - -class NewLinkWindow(QWidget): - def __init__(self, dock): - QWidget.__init__(self) - self.dock = dock - self.setLayout(QVBoxLayout()) - layout = self.layout() - - explanationLabel = QLabel("Select a package and then click Add button.") - boxLabel = QLabel("Paste URLs here:") - self.box = QTextEdit() - - save = QPushButton("Add") - - layout.addWidget(explanationLabel) - layout.addWidget(boxLabel) - layout.addWidget(self.box) - layout.addWidget(save) - - self.connect(save, SIGNAL("clicked()"), self.dock.slotDone) diff --git a/module/gui/MainWindow.py b/module/gui/MainWindow.py deleted file mode 100644 index c71112e9b..000000000 --- a/module/gui/MainWindow.py +++ /dev/null @@ -1,697 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from os.path import join - -from module.gui.PackageDock import * -from module.gui.LinkDock import * -from module.gui.CaptchaDock import CaptchaDock -from module.gui.SettingsWidget import SettingsWidget - -from module.gui.Collector import CollectorView, Package, Link -from module.gui.Queue import QueueView -from module.gui.Overview import OverviewView -from module.gui.Accounts import AccountView -from module.gui.AccountEdit import AccountEdit - -from module.remote.thriftbackend.ThriftClient import AccountInfo - -class MainWindow(QMainWindow): - def __init__(self, connector): - """ - set up main window - """ - QMainWindow.__init__(self) - #window stuff - self.setWindowTitle(_("pyLoad Client")) - self.setWindowIcon(QIcon(join(pypath, "icons","logo.png"))) - self.resize(1000,600) - - #layout version - self.version = 3 - - #init docks - self.newPackDock = NewPackageDock() - self.addDockWidget(Qt.RightDockWidgetArea, self.newPackDock) - self.connect(self.newPackDock, SIGNAL("done"), self.slotAddPackage) - self.captchaDock = CaptchaDock() - self.addDockWidget(Qt.BottomDockWidgetArea, self.captchaDock) - self.newLinkDock = NewLinkDock() - self.addDockWidget(Qt.RightDockWidgetArea, self.newLinkDock) - self.connect(self.newLinkDock, SIGNAL("done"), self.slotAddLinksToPackage) - - #central widget, layout - self.masterlayout = QVBoxLayout() - lw = QWidget() - lw.setLayout(self.masterlayout) - self.setCentralWidget(lw) - - #status - self.statusw = QFrame() - self.statusw.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) - self.statusw.setLineWidth(2) - self.statusw.setLayout(QGridLayout()) - #palette = self.statusw.palette() - #palette.setColor(QPalette.Window, QColor(255, 255, 255)) - #self.statusw.setPalette(palette) - #self.statusw.setAutoFillBackground(True) - l = self.statusw.layout() - - class BoldLabel(QLabel): - def __init__(self, text): - QLabel.__init__(self, text) - f = self.font() - f.setBold(True) - self.setFont(f) - self.setAlignment(Qt.AlignRight) - - class Seperator(QFrame): - def __init__(self): - QFrame.__init__(self) - self.setFrameShape(QFrame.VLine) - self.setFrameShadow(QFrame.Sunken) - - l.addWidget(BoldLabel(_("Packages:")), 0, 0) - self.packageCount = QLabel("0") - l.addWidget(self.packageCount, 0, 1) - - l.addWidget(BoldLabel(_("Files:")), 0, 2) - self.fileCount = QLabel("0") - l.addWidget(self.fileCount, 0, 3) - - l.addWidget(BoldLabel(_("Status:")), 0, 4) - self.status = QLabel("running") - l.addWidget(self.status, 0, 5) - - l.addWidget(BoldLabel(_("Space:")), 0, 6) - self.space = QLabel("") - l.addWidget(self.space, 0, 7) - - l.addWidget(BoldLabel(_("Speed:")), 0, 8) - self.speed = QLabel("") - l.addWidget(self.speed, 0, 9) - - #l.addWidget(BoldLabel(_("Max. downloads:")), 0, 9) - #l.addWidget(BoldLabel(_("Max. chunks:")), 1, 9) - #self.maxDownloads = QSpinBox() - #self.maxDownloads.setEnabled(False) - #self.maxChunks = QSpinBox() - #self.maxChunks.setEnabled(False) - #l.addWidget(self.maxDownloads, 0, 10) - #l.addWidget(self.maxChunks, 1, 10) - - #set menubar and statusbar - self.menubar = self.menuBar() - #self.statusbar = self.statusBar() - #self.connect(self.statusbar, SIGNAL("showMsg"), self.statusbar.showMessage) - #self.serverStatus = QLabel(_("Status: Not Connected")) - #self.statusbar.addPermanentWidget(self.serverStatus) - - #menu - self.menus = {"file": self.menubar.addMenu(_("File")), - "connections": self.menubar.addMenu(_("Connections"))} - - #menu actions - self.mactions = {"exit": QAction(_("Exit"), self.menus["file"]), - "manager": QAction(_("Connection manager"), self.menus["connections"])} - - #add menu actions - self.menus["file"].addAction(self.mactions["exit"]) - self.menus["connections"].addAction(self.mactions["manager"]) - - #toolbar - self.actions = {} - self.init_toolbar() - - #tabs - self.tabw = QTabWidget() - self.tabs = {"overview": {"w": QWidget()}, - "queue": {"w": QWidget()}, - "collector": {"w": QWidget()}, - "accounts": {"w": QWidget()}, - "settings": {}} - #self.tabs["settings"]["s"] = QScrollArea() - self.tabs["settings"]["w"] = SettingsWidget() - #self.tabs["settings"]["s"].setWidgetResizable(True) - #self.tabs["settings"]["s"].setWidget(self.tabs["settings"]["w"]) - self.tabs["log"] = {"w":QWidget()} - self.tabw.addTab(self.tabs["overview"]["w"], _("Overview")) - self.tabw.addTab(self.tabs["queue"]["w"], _("Queue")) - self.tabw.addTab(self.tabs["collector"]["w"], _("Collector")) - self.tabw.addTab(self.tabs["accounts"]["w"], _("Accounts")) - self.tabw.addTab(self.tabs["settings"]["w"], _("Settings")) - self.tabw.addTab(self.tabs["log"]["w"], _("Log")) - - #init tabs - self.init_tabs(connector) - - #context menus - self.init_context() - - #layout - self.masterlayout.addWidget(self.tabw) - self.masterlayout.addWidget(self.statusw) - - #signals.. - self.connect(self.mactions["manager"], SIGNAL("triggered()"), self.slotShowConnector) - - self.connect(self.tabs["queue"]["view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotQueueContextMenu) - self.connect(self.tabs["collector"]["package_view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotCollectorContextMenu) - self.connect(self.tabs["accounts"]["view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotAccountContextMenu) - - self.connect(self.tabw, SIGNAL("currentChanged(int)"), self.slotTabChanged) - - self.lastAddedID = None - - self.connector = connector - - def init_toolbar(self): - """ - create toolbar - """ - self.toolbar = self.addToolBar(_("Hide Toolbar")) - self.toolbar.setObjectName("Main Toolbar") - self.toolbar.setIconSize(QSize(30,30)) - self.toolbar.setMovable(False) - self.actions["toggle_status"] = self.toolbar.addAction(_("Toggle Pause/Resume")) - pricon = QIcon() - pricon.addFile(join(pypath, "icons","toolbar_start.png"), QSize(), QIcon.Normal, QIcon.Off) - pricon.addFile(join(pypath, "icons","toolbar_pause.png"), QSize(), QIcon.Normal, QIcon.On) - self.actions["toggle_status"].setIcon(pricon) - self.actions["toggle_status"].setCheckable(True) - self.actions["status_stop"] = self.toolbar.addAction(QIcon(join(pypath, "icons","toolbar_stop.png")), _("Stop")) - self.toolbar.addSeparator() - self.actions["add"] = self.toolbar.addAction(QIcon(join(pypath, "icons","toolbar_add.png")), _("Add")) - self.toolbar.addSeparator() - self.actions["clipboard"] = self.toolbar.addAction(QIcon(join(pypath, "icons","clipboard.png")), _("Check Clipboard")) - self.actions["clipboard"].setCheckable(True) - - self.connect(self.actions["toggle_status"], SIGNAL("toggled(bool)"), self.slotToggleStatus) - self.connect(self.actions["clipboard"], SIGNAL("toggled(bool)"), self.slotToggleClipboard) - self.connect(self.actions["status_stop"], SIGNAL("triggered()"), self.slotStatusStop) - self.addMenu = QMenu() - packageAction = self.addMenu.addAction(_("Package")) - containerAction = self.addMenu.addAction(_("Container")) - accountAction = self.addMenu.addAction(_("Account")) - linksAction = self.addMenu.addAction(_("Links")) - self.connect(self.actions["add"], SIGNAL("triggered()"), self.slotAdd) - self.connect(packageAction, SIGNAL("triggered()"), self.slotShowAddPackage) - self.connect(containerAction, SIGNAL("triggered()"), self.slotShowAddContainer) - self.connect(accountAction, SIGNAL("triggered()"), self.slotNewAccount) - self.connect(linksAction, SIGNAL("triggered()"), self.slotShowAddLinks) - - def init_tabs(self, connector): - """ - create tabs - """ - #overview - self.tabs["overview"]["l"] = QGridLayout() - self.tabs["overview"]["w"].setLayout(self.tabs["overview"]["l"]) - self.tabs["overview"]["view"] = OverviewView(connector) - self.tabs["overview"]["l"].addWidget(self.tabs["overview"]["view"]) - - #queue - self.tabs["queue"]["l"] = QGridLayout() - self.tabs["queue"]["w"].setLayout(self.tabs["queue"]["l"]) - self.tabs["queue"]["view"] = QueueView(connector) - self.tabs["queue"]["l"].addWidget(self.tabs["queue"]["view"]) - - #collector - toQueue = QPushButton(_("Push selected packages to queue")) - self.tabs["collector"]["l"] = QGridLayout() - self.tabs["collector"]["w"].setLayout(self.tabs["collector"]["l"]) - self.tabs["collector"]["package_view"] = CollectorView(connector) - self.tabs["collector"]["l"].addWidget(self.tabs["collector"]["package_view"], 0, 0) - self.tabs["collector"]["l"].addWidget(toQueue, 1, 0) - self.connect(toQueue, SIGNAL("clicked()"), self.slotPushPackageToQueue) - self.tabs["collector"]["package_view"].setContextMenuPolicy(Qt.CustomContextMenu) - self.tabs["queue"]["view"].setContextMenuPolicy(Qt.CustomContextMenu) - - #log - self.tabs["log"]["l"] = QGridLayout() - self.tabs["log"]["w"].setLayout(self.tabs["log"]["l"]) - self.tabs["log"]["text"] = QTextEdit() - self.tabs["log"]["text"].logOffset = 0 - self.tabs["log"]["text"].setReadOnly(True) - self.connect(self.tabs["log"]["text"], SIGNAL("append(QString)"), self.tabs["log"]["text"].append) - self.tabs["log"]["l"].addWidget(self.tabs["log"]["text"]) - - #accounts - self.tabs["accounts"]["view"] = AccountView(connector) - self.tabs["accounts"]["w"].setLayout(QVBoxLayout()) - self.tabs["accounts"]["w"].layout().addWidget(self.tabs["accounts"]["view"]) - newbutton = QPushButton(_("New Account")) - self.tabs["accounts"]["w"].layout().addWidget(newbutton) - self.connect(newbutton, SIGNAL("clicked()"), self.slotNewAccount) - self.tabs["accounts"]["view"].setContextMenuPolicy(Qt.CustomContextMenu) - - def init_context(self): - """ - create context menus - """ - self.activeMenu = None - #queue - self.queueContext = QMenu() - self.queueContext.buttons = {} - self.queueContext.item = (None, None) - self.queueContext.buttons["remove"] = QAction(QIcon(join(pypath, "icons","remove_small.png")), _("Remove"), self.queueContext) - self.queueContext.buttons["restart"] = QAction(QIcon(join(pypath, "icons","refresh_small.png")), _("Restart"), self.queueContext) - self.queueContext.buttons["pull"] = QAction(QIcon(join(pypath, "icons","pull_small.png")), _("Pull out"), self.queueContext) - self.queueContext.buttons["abort"] = QAction(QIcon(join(pypath, "icons","abort.png")), _("Abort"), self.queueContext) - self.queueContext.buttons["edit"] = QAction(QIcon(join(pypath, "icons","edit_small.png")), _("Edit Name"), self.queueContext) - self.queueContext.addAction(self.queueContext.buttons["pull"]) - self.queueContext.addAction(self.queueContext.buttons["edit"]) - self.queueContext.addAction(self.queueContext.buttons["remove"]) - self.queueContext.addAction(self.queueContext.buttons["restart"]) - self.queueContext.addAction(self.queueContext.buttons["abort"]) - self.connect(self.queueContext.buttons["remove"], SIGNAL("triggered()"), self.slotRemoveDownload) - self.connect(self.queueContext.buttons["restart"], SIGNAL("triggered()"), self.slotRestartDownload) - self.connect(self.queueContext.buttons["pull"], SIGNAL("triggered()"), self.slotPullOutPackage) - self.connect(self.queueContext.buttons["abort"], SIGNAL("triggered()"), self.slotAbortDownload) - self.connect(self.queueContext.buttons["edit"], SIGNAL("triggered()"), self.slotEditPackage) - - #collector - self.collectorContext = QMenu() - self.collectorContext.buttons = {} - self.collectorContext.item = (None, None) - self.collectorContext.buttons["remove"] = QAction(QIcon(join(pypath, "icons","remove_small.png")), _("Remove"), self.collectorContext) - self.collectorContext.buttons["push"] = QAction(QIcon(join(pypath, "icons","push_small.png")), _("Push to queue"), self.collectorContext) - self.collectorContext.buttons["edit"] = QAction(QIcon(join(pypath, "icons","edit_small.png")), _("Edit Name"), self.collectorContext) - self.collectorContext.buttons["restart"] = QAction(QIcon(join(pypath, "icons","refresh_small.png")), _("Restart"), self.collectorContext) - self.collectorContext.buttons["refresh"] = QAction(QIcon(join(pypath, "icons","refresh1_small.png")),_("Refresh Status"), self.collectorContext) - self.collectorContext.addAction(self.collectorContext.buttons["push"]) - self.collectorContext.addSeparator() - self.collectorContext.buttons["add"] = self.collectorContext.addMenu(QIcon(join(pypath, "icons","add_small.png")), _("Add")) - self.collectorContext.addAction(self.collectorContext.buttons["edit"]) - self.collectorContext.addAction(self.collectorContext.buttons["remove"]) - self.collectorContext.addAction(self.collectorContext.buttons["restart"]) - self.collectorContext.addSeparator() - self.collectorContext.addAction(self.collectorContext.buttons["refresh"]) - packageAction = self.collectorContext.buttons["add"].addAction(_("Package")) - containerAction = self.collectorContext.buttons["add"].addAction(_("Container")) - linkAction = self.collectorContext.buttons["add"].addAction(_("Links")) - self.connect(self.collectorContext.buttons["remove"], SIGNAL("triggered()"), self.slotRemoveDownload) - self.connect(self.collectorContext.buttons["push"], SIGNAL("triggered()"), self.slotPushPackageToQueue) - self.connect(self.collectorContext.buttons["edit"], SIGNAL("triggered()"), self.slotEditPackage) - self.connect(self.collectorContext.buttons["restart"], SIGNAL("triggered()"), self.slotRestartDownload) - self.connect(self.collectorContext.buttons["refresh"], SIGNAL("triggered()"), self.slotRefreshPackage) - self.connect(packageAction, SIGNAL("triggered()"), self.slotShowAddPackage) - self.connect(containerAction, SIGNAL("triggered()"), self.slotShowAddContainer) - self.connect(linkAction, SIGNAL("triggered()"), self.slotShowAddLinks) - - self.accountContext = QMenu() - self.accountContext.buttons = {} - self.accountContext.buttons["add"] = QAction(QIcon(join(pypath, "icons","add_small.png")), _("Add"), self.accountContext) - self.accountContext.buttons["remove"] = QAction(QIcon(join(pypath, "icons","remove_small.png")), _("Remove"), self.accountContext) - self.accountContext.buttons["edit"] = QAction(QIcon(join(pypath, "icons","edit_small.png")), _("Edit"), self.accountContext) - self.accountContext.addAction(self.accountContext.buttons["add"]) - self.accountContext.addAction(self.accountContext.buttons["edit"]) - self.accountContext.addAction(self.accountContext.buttons["remove"]) - self.connect(self.accountContext.buttons["add"], SIGNAL("triggered()"), self.slotNewAccount) - self.connect(self.accountContext.buttons["edit"], SIGNAL("triggered()"), self.slotEditAccount) - self.connect(self.accountContext.buttons["remove"], SIGNAL("triggered()"), self.slotRemoveAccount) - - def slotToggleStatus(self, status): - """ - pause/start toggle (toolbar) - """ - self.emit(SIGNAL("setDownloadStatus"), status) - - def slotStatusStop(self): - """ - stop button (toolbar) - """ - self.emit(SIGNAL("stopAllDownloads")) - - def slotAdd(self): - """ - add button (toolbar) - show context menu (choice: links/package) - """ - self.addMenu.exec_(QCursor.pos()) - - def slotShowAddPackage(self): - """ - action from add-menu - show new-package dock - """ - self.tabw.setCurrentIndex(1) - self.newPackDock.show() - - def slotShowAddLinks(self): - """ - action from add-menu - show new-links dock - """ - self.tabw.setCurrentIndex(1) - self.newLinkDock.show() - - def slotShowConnector(self): - """ - connectionmanager action triggered - let main to the stuff - """ - self.emit(SIGNAL("connector")) - - def slotAddPackage(self, name, links, password=None): - """ - new package - let main to the stuff - """ - self.emit(SIGNAL("addPackage"), name, links, password) - - def slotAddLinksToPackage(self, links): - """ - adds links to currently selected package - only in collector - """ - if self.tabw.currentIndex() != 1: - return - - smodel = self.tabs["collector"]["package_view"].selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - if isinstance(item, Package): - self.connector.proxy.addFiles(item.id, links) - break - - def slotShowAddContainer(self): - """ - action from add-menu - show file selector, emit upload - """ - typeStr = ";;".join([ - _("All Container Types (%s)") % "*.dlc *.ccf *.rsdf *.txt", - _("DLC (%s)") % "*.dlc", - _("CCF (%s)") % "*.ccf", - _("RSDF (%s)") % "*.rsdf", - _("Text Files (%s)") % "*.txt" - ]) - fileNames = QFileDialog.getOpenFileNames(self, _("Open container"), "", typeStr) - for name in fileNames: - self.emit(SIGNAL("addContainer"), str(name)) - - def slotPushPackageToQueue(self): - """ - push collector pack to queue - get child ids - let main to the rest - """ - smodel = self.tabs["collector"]["package_view"].selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - if isinstance(item, Package): - self.emit(SIGNAL("pushPackageToQueue"), item.id) - else: - self.emit(SIGNAL("pushPackageToQueue"), item.package.id) - - def saveWindow(self): - """ - get window state/geometry - pass data to main - """ - state_raw = self.saveState(self.version) - geo_raw = self.saveGeometry() - - state = str(state_raw.toBase64()) - geo = str(geo_raw.toBase64()) - - self.emit(SIGNAL("saveMainWindow"), state, geo) - - def closeEvent(self, event): - """ - somebody wants to close me! - let me first save my state - """ - self.saveWindow() - event.ignore() - self.hide() - self.emit(SIGNAL("hidden")) - - # quit when no tray is available - if not QSystemTrayIcon.isSystemTrayAvailable(): - self.emit(SIGNAL("Quit")) - - def restoreWindow(self, state, geo): - """ - restore window state/geometry - """ - state = QByteArray(state) - geo = QByteArray(geo) - - state_raw = QByteArray.fromBase64(state) - geo_raw = QByteArray.fromBase64(geo) - - self.restoreState(state_raw, self.version) - self.restoreGeometry(geo_raw) - - def slotQueueContextMenu(self, pos): - """ - custom context menu in queue view requested - """ - globalPos = self.tabs["queue"]["view"].mapToGlobal(pos) - i = self.tabs["queue"]["view"].indexAt(pos) - if not i: - return - item = i.internalPointer() - menuPos = QCursor.pos() - menuPos.setX(menuPos.x()+2) - self.activeMenu = self.queueContext - showAbort = False - if isinstance(item, Link) and item.data["downloading"]: - showAbort = True - elif isinstance(item, Package): - for child in item.children: - if child.data["downloading"]: - showAbort = True - break - if showAbort: - self.queueContext.buttons["abort"].setEnabled(True) - else: - self.queueContext.buttons["abort"].setEnabled(False) - if isinstance(item, Package): - self.queueContext.index = i - #self.queueContext.buttons["remove"].setEnabled(True) - #self.queueContext.buttons["restart"].setEnabled(True) - self.queueContext.buttons["pull"].setEnabled(True) - self.queueContext.buttons["edit"].setEnabled(True) - elif isinstance(item, Link): - self.collectorContext.index = i - self.collectorContext.buttons["edit"].setEnabled(False) - self.collectorContext.buttons["remove"].setEnabled(True) - self.collectorContext.buttons["push"].setEnabled(False) - self.collectorContext.buttons["restart"].setEnabled(True) - else: - self.queueContext.index = None - #self.queueContext.buttons["remove"].setEnabled(False) - #self.queueContext.buttons["restart"].setEnabled(False) - self.queueContext.buttons["pull"].setEnabled(False) - self.queueContext.buttons["edit"].setEnabled(False) - self.queueContext.exec_(menuPos) - - def slotCollectorContextMenu(self, pos): - """ - custom context menu in package collector view requested - """ - globalPos = self.tabs["collector"]["package_view"].mapToGlobal(pos) - i = self.tabs["collector"]["package_view"].indexAt(pos) - if not i: - return - item = i.internalPointer() - menuPos = QCursor.pos() - menuPos.setX(menuPos.x()+2) - self.activeMenu = self.collectorContext - if isinstance(item, Package): - self.collectorContext.index = i - self.collectorContext.buttons["edit"].setEnabled(True) - self.collectorContext.buttons["remove"].setEnabled(True) - self.collectorContext.buttons["push"].setEnabled(True) - self.collectorContext.buttons["restart"].setEnabled(True) - elif isinstance(item, Link): - self.collectorContext.index = i - self.collectorContext.buttons["edit"].setEnabled(False) - self.collectorContext.buttons["remove"].setEnabled(True) - self.collectorContext.buttons["push"].setEnabled(False) - self.collectorContext.buttons["restart"].setEnabled(True) - else: - self.collectorContext.index = None - self.collectorContext.buttons["edit"].setEnabled(False) - self.collectorContext.buttons["remove"].setEnabled(False) - self.collectorContext.buttons["push"].setEnabled(False) - self.collectorContext.buttons["restart"].setEnabled(False) - self.collectorContext.exec_(menuPos) - - def slotLinkCollectorContextMenu(self, pos): - """ - custom context menu in link collector view requested - """ - pass - - def slotRestartDownload(self): - """ - restart download action is triggered - """ - smodel = self.tabs["queue"]["view"].selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - self.emit(SIGNAL("restartDownload"), item.id, isinstance(item, Package)) - - def slotRemoveDownload(self): - """ - remove download action is triggered - """ - if self.activeMenu == self.queueContext: - view = self.tabs["queue"]["view"] - else: - view = self.tabs["collector"]["package_view"] - smodel = view.selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - self.emit(SIGNAL("removeDownload"), item.id, isinstance(item, Package)) - - def slotToggleClipboard(self, status): - """ - check clipboard (toolbar) - """ - self.emit(SIGNAL("setClipboardStatus"), status) - - def slotEditPackage(self): - # in Queue, only edit name - if self.activeMenu == self.queueContext: - view = self.tabs["queue"]["view"] - else: - view = self.tabs["collector"]["package_view"] - view.edit(self.activeMenu.index) - - def slotEditCommit(self, editor): - self.emit(SIGNAL("changePackageName"), self.activeMenu.index.internalPointer().id, editor.text()) - - def slotPullOutPackage(self): - """ - pull package out of the queue - """ - smodel = self.tabs["queue"]["view"].selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - if isinstance(item, Package): - self.emit(SIGNAL("pullOutPackage"), item.id) - else: - self.emit(SIGNAL("pullOutPackage"), item.package.id) - - def slotAbortDownload(self): - view = self.tabs["queue"]["view"] - smodel = view.selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - self.emit(SIGNAL("abortDownload"), item.id, isinstance(item, Package)) - - # TODO disabled because changing desktop on linux, main window disappears - #def changeEvent(self, e): - # if e.type() == QEvent.WindowStateChange and self.isMinimized(): - # e.ignore() - # self.hide() - # self.emit(SIGNAL("hidden")) - # else: - # super(MainWindow, self).changeEvent(e) - - def slotTabChanged(self, index): - if index == 2: - self.emit(SIGNAL("reloadAccounts")) - elif index == 3: - self.tabs["settings"]["w"].loadConfig() - - def slotRefreshPackage(self): - smodel = self.tabs["collector"]["package_view"].selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - pid = item.id - if isinstance(item, Link): - pid = item.package.id - self.emit(SIGNAL("refreshStatus"), pid) - - def slotNewAccount(self): - types = self.connector.proxy.getAccountTypes() - self.accountEdit = AccountEdit.newAccount(types) - - #TODO make more easy n1, n2, n3 - def save(data): - if data["password"]: - self.accountEdit.close() - n1 = data["acctype"] - n2 = data["login"] - n3 = data["password"] - self.connector.updateAccount(n1, n2, n3, None) - - self.accountEdit.connect(self.accountEdit, SIGNAL("done"), save) - self.accountEdit.show() - - def slotEditAccount(self): - types = self.connector.getAccountTypes() - - data = self.tabs["accounts"]["view"].selectedIndexes() - if len(data) < 1: - return - - data = data[0].internalPointer() - - self.accountEdit = AccountEdit.editAccount(types, data) - - #TODO make more easy n1, n2, n3 - #TODO reload accounts tab after insert of edit account - #TODO if account does not exist give error - def save(data): - self.accountEdit.close() - n1 = data["acctype"] - n2 = data["login"] - if data["password"]: - n3 = data["password"] - self.connector.updateAccount(n1, n2, n3, None) - - self.accountEdit.connect(self.accountEdit, SIGNAL("done"), save) - self.accountEdit.show() - - def slotRemoveAccount(self): - data = self.tabs["accounts"]["view"].selectedIndexes() - if len(data) < 1: - return - - data = data[0].internalPointer() - - self.connector.removeAccount(data.type, data.login) - - def slotAccountContextMenu(self, pos): - globalPos = self.tabs["accounts"]["view"].mapToGlobal(pos) - i = self.tabs["accounts"]["view"].indexAt(pos) - if not i: - return - - data = i.internalPointer() - - if data is None: - self.accountContext.buttons["edit"].setEnabled(False) - self.accountContext.buttons["remove"].setEnabled(False) - else: - self.accountContext.buttons["edit"].setEnabled(True) - self.accountContext.buttons["remove"].setEnabled(True) - - menuPos = QCursor.pos() - menuPos.setX(menuPos.x()+2) - self.accountContext.exec_(menuPos) diff --git a/module/gui/Overview.py b/module/gui/Overview.py deleted file mode 100644 index 183383b5e..000000000 --- a/module/gui/Overview.py +++ /dev/null @@ -1,197 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from module.utils import formatSpeed, formatSize - -class OverviewModel(QAbstractListModel): - PackageName = 10 - Progress = 11 - PartsFinished = 12 - Parts = 13 - ETA = 14 - Speed = 15 - CurrentSize = 16 - MaxSize = 17 - Status = 18 - - def __init__(self, view, connector): - QAbstractListModel.__init__(self) - - self.packages = [] - - def queueChanged(self): #dirty.. - self.beginResetModel() - - self.packages = [] - - def partsFinished(p): - f = 0 - for c in p.children: - if c.data["status"] == 0: - f += 1 - return f - - def maxSize(p): - ms = 0 - cs = 0 - for c in p.children: - try: - s = c.data["downloading"]["size"] - except: - s = c.data["size"] - if c.data["downloading"]: - cs += s - c.data["downloading"]["bleft"] - elif self.queue.getProgress(c, False) == 100: - cs += s - ms += s - return ms, cs - - def getProgress(p): - for c in p.children: - if c.data["status"] == 13: - pass # TODO return _("Unpacking"), int(c.data["progress"]) - return _("Downloading"), self.queue.getProgress(p) - - d = self.queue._data - for p in d: - status, progress = getProgress(p) - maxsize, currentsize = maxSize(p) - speed = self.queue.getSpeed(p) - if speed: - eta = (maxsize - (maxsize * (progress/100.0)))/speed - else: - eta = 0 - if not speed and not progress: - status = _("Queued") - info = { - OverviewModel.PackageName: p.data["name"], - OverviewModel.Progress: progress, - OverviewModel.PartsFinished: partsFinished(p), - OverviewModel.Parts: len(p.children), - OverviewModel.ETA: int(eta), - OverviewModel.Speed: speed, - OverviewModel.CurrentSize: currentsize, - OverviewModel.MaxSize: maxsize, - OverviewModel.Status: status, - } - - self.packages.append(info) - - self.endResetModel() - - def headerData(self, section, orientation, role=Qt.DisplayRole): - return QVariant(_("Package")) - - def rowCount(self, parent=QModelIndex()): - return len(self.packages) - - def data(self, index, role=Qt.DisplayRole): - if role in [OverviewModel.PackageName, OverviewModel.Progress, OverviewModel.PartsFinished, OverviewModel.Parts, OverviewModel.ETA, OverviewModel.Speed, OverviewModel.CurrentSize, OverviewModel.MaxSize, OverviewModel.Status]: - return QVariant(self.packages[index.row()][role]) - return QVariant() - -class OverviewView(QListView): - def __init__(self, connector): - QListView.__init__(self) - self.setModel(OverviewModel(self, connector)) - - self.setAlternatingRowColors(True) - self.delegate = OverviewDelegate(self) - self.setItemDelegate(self.delegate) - -class OverviewDelegate(QItemDelegate): - def __init__(self, parent): - QItemDelegate.__init__(self, parent) - self.parent = parent - self.model = parent.model() - - def paint(self, painter, option, index): - option.rect.setHeight(59+16) - option.rect.setWidth(self.parent.width()-20) - - #if option.state & QStyle.State_Selected: - # painter.fillRect(option.rect, option.palette.color(QPalette.Highlight)) - - packagename = index.data(OverviewModel.PackageName).toString() - partsf = index.data(OverviewModel.PartsFinished).toString() - parts = index.data(OverviewModel.Parts).toString() - eta = int(index.data(OverviewModel.ETA).toString()) - speed = index.data(OverviewModel.Speed).toString() or 0 - progress = int(index.data(OverviewModel.Progress).toString()) - currentSize = int(index.data(OverviewModel.CurrentSize).toString()) - maxSize = int(index.data(OverviewModel.MaxSize).toString()) - status = index.data(OverviewModel.Status).toString() - - def formatEta(seconds): #TODO add to utils - if seconds <= 0: return "" - hours, seconds = divmod(seconds, 3600) - minutes, seconds = divmod(seconds, 60) - return _("ETA: ") + "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - - statusline = QString(_("Parts: ") + "%s/%s" % (partsf, parts)) - if partsf == parts: - speedline = _("Finished") - elif not status == _("Downloading"): - speedline = QString(status) - else: - speedline = QString(formatEta(eta) + " " + _("Speed: %s") % formatSpeed(speed)) - - if progress in (0,100): - sizeline = QString(_("Size:") + "%s" % formatSize(maxSize)) - else: - sizeline = QString(_("Size:") + "%s / %s" % (formatSize(currentSize), formatSize(maxSize))) - - f = painter.font() - f.setPointSize(12) - f.setBold(True) - painter.setFont(f) - - r = option.rect.adjusted(4, 4, -4, -4) - painter.drawText(r.left(), r.top(), r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, packagename) - newr = painter.boundingRect(r.left(), r.top(), r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, packagename) - - f.setPointSize(10) - f.setBold(False) - painter.setFont(f) - - painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, statusline) - painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignHCenter, sizeline) - painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignRight, speedline) - newr = painter.boundingRect(r.left(), newr.bottom()+2, r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, statusline) - newr.setTop(newr.bottom()+8) - newr.setBottom(newr.top()+20) - newr.setRight(self.parent.width()-25) - - f.setPointSize(10) - painter.setFont(f) - - opts = QStyleOptionProgressBarV2() - opts.maximum = 100 - opts.minimum = 0 - opts.progress = progress - opts.rect = newr - opts.textVisible = True - opts.textAlignment = Qt.AlignCenter - opts.text = QString.number(opts.progress) + "%" - QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter) - - def sizeHint(self, option, index): - return QSize(self.parent.width()-22, 59+16) diff --git a/module/gui/PackageDock.py b/module/gui/PackageDock.py deleted file mode 100644 index 73db8f177..000000000 --- a/module/gui/PackageDock.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" -import re - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -class NewPackageDock(QDockWidget): - def __init__(self): - QDockWidget.__init__(self, _("New Package")) - self.setObjectName("New Package Dock") - self.widget = NewPackageWindow(self) - self.setWidget(self.widget) - self.setAllowedAreas(Qt.RightDockWidgetArea|Qt.LeftDockWidgetArea) - self.hide() - - def slotDone(self): - text = str(self.widget.box.toPlainText()) - pw = str(self.widget.passwordInput.text()) - if not pw: - pw = None - lines = [] - for line in text.splitlines(): - line = line.strip() - if not line: - continue - lines.append(line) - self.emit(SIGNAL("done"), str(self.widget.nameInput.text()), lines, pw) - self.widget.nameInput.setText("") - self.widget.passwordInput.setText("") - self.widget.box.clear() - self.hide() - - def parseUri(self): - - text=str(self.widget.box.toPlainText()) - self.widget.box.setText("") - result = re.findall(r"(?:ht|f)tps?:\/\/[a-zA-Z0-9\-\.\/\?=_&%#]+[<| |\"|\'|\r|\n|\t]{1}", text) - for url in result: - if "\n" or "\t" or "\r" or "\"" or "<" or "'" in url: - url = url[:-1] - self.widget.box.append("%s " % url) - -class NewPackageWindow(QWidget): - def __init__(self, dock): - QWidget.__init__(self) - self.dock = dock - self.setLayout(QGridLayout()) - layout = self.layout() - - nameLabel = QLabel(_("Name")) - nameInput = QLineEdit() - passwordLabel = QLabel(_("Password")) - passwordInput = QLineEdit() - - linksLabel = QLabel(_("Links in this Package")) - - self.box = QTextEdit() - self.nameInput = nameInput - self.passwordInput = passwordInput - - save = QPushButton(_("Create")) - parseUri = QPushButton(_("Filter URLs")) - - layout.addWidget(nameLabel, 0, 0) - layout.addWidget(nameInput, 0, 1) - layout.addWidget(passwordLabel, 1, 0) - layout.addWidget(passwordInput, 1, 1) - layout.addWidget(linksLabel, 2, 0, 1, 2) - layout.addWidget(self.box, 3, 0, 1, 2) - layout.addWidget(parseUri, 4, 0, 1, 2) - layout.addWidget(save, 5, 0, 1, 2) - - self.connect(save, SIGNAL("clicked()"), self.dock.slotDone) - self.connect(parseUri, SIGNAL("clicked()"), self.dock.parseUri)
\ No newline at end of file diff --git a/module/gui/Queue.py b/module/gui/Queue.py deleted file mode 100644 index 0a0cbb810..000000000 --- a/module/gui/Queue.py +++ /dev/null @@ -1,390 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from time import time - -from module.remote.thriftbackend.ThriftClient import Destination -from module.gui.Collector import CollectorModel, Package, Link, CollectorView, statusMapReverse -from module.utils import formatSize, formatSpeed - -class QueueModel(CollectorModel): - """ - model for the queue view, inherits from CollectorModel - """ - - def __init__(self, view, connector): - CollectorModel.__init__(self, view, connector) - self.cols = 6 - self.wait_dict = {} - - self.updater = self.QueueUpdater(self.interval) - self.connect(self.updater, SIGNAL("update()"), self.update) - - class QueueUpdater(QObject): - """ - timer which emits signal for a download status reload - @TODO: make intervall configurable - """ - - def __init__(self, interval): - QObject.__init__(self) - - self.interval = interval - self.timer = QTimer() - self.timer.connect(self.timer, SIGNAL("timeout()"), self, SIGNAL("update()")) - - def start(self): - self.timer.start(1000) - - def stop(self): - self.timer.stop() - - def start(self): - self.updater.start() - - def stop(self): - self.updater.stop() - - def fullReload(self): - """ - reimplements CollectorModel.fullReload, because we want the Queue data - """ - self._data = [] - order = self.connector.getPackageOrder(Destination.Queue) - self.beginInsertRows(QModelIndex(), 0, len(order.values())) - for position, pid in order.iteritems(): - pack = self.connector.getPackageData(pid) - package = Package(pack) - self._data.append(package) - self._data = sorted(self._data, key=lambda p: p.data["order"]) - self.endInsertRows() - self.updateCount() - - def insertEvent(self, event): - """ - wrap CollectorModel.insertEvent to update the element count - """ - CollectorModel.insertEvent(self, event) - self.updateCount() - - def removeEvent(self, event): - """ - wrap CollectorModel.removeEvent to update the element count - """ - CollectorModel.removeEvent(self, event) - self.updateCount() - - def updateEvent(self, event): - """ - wrap CollectorModel.updateEvent to update the element count - """ - CollectorModel.updateEvent(self, event) - self.updateCount() - - def updateCount(self): - """ - calculate package- and filecount for statusbar, - ugly?: Overview connects to this signal for updating - """ - packageCount = len(self._data) - fileCount = 0 - for p in self._data: - fileCount += len(p.children) - self.mutex.unlock() - self.emit(SIGNAL("updateCount"), packageCount, fileCount) - self.mutex.lock() - - def update(self): - """ - update slot for download status updating - """ - locker = QMutexLocker(self.mutex) - downloading = self.connector.statusDownloads() - if not downloading: - return - for p, pack in enumerate(self._data): - for d in downloading: - child = pack.getChild(d.fid) - if child: - dd = { - "name": d.name, - "speed": d.speed, - "eta": d.eta, - "format_eta": d.format_eta, - "bleft": d.bleft, - "size": d.size, - "format_size": d.format_size, - "percent": d.percent, - "status": d.status, - "statusmsg": d.statusmsg, - "format_wait": d.format_wait, - "wait_until": d.wait_until - } - child.data["downloading"] = dd - k = pack.getChildKey(d.fid) - self.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), self.index(k, 0, self.index(p, 0)), self.index(k, self.cols, self.index(p, self.cols))) - self.updateCount() - - def headerData(self, section, orientation, role=Qt.DisplayRole): - """ - returns column heading - """ - if orientation == Qt.Horizontal and role == Qt.DisplayRole: - if section == 0: - return QVariant(_("Name")) - elif section == 2: - return QVariant(_("Status")) - elif section == 1: - return QVariant(_("Plugin")) - elif section == 3: - return QVariant(_("Size")) - elif section == 4: - return QVariant(_("ETA")) - elif section == 5: - return QVariant(_("Progress")) - return QVariant() - - def getWaitingProgress(self, item): - """ - returns time to wait, caches startingtime to provide progress - """ - locker = QMutexLocker(self.mutex) - if isinstance(item, Link): - if item.data["status"] == 5 and item.data["downloading"]: - until = float(item.data["downloading"]["wait_until"]) - try: - since, until_old = self.wait_dict[item.id] - if not until == until_old: - raise Exception - except: - since = time() - self.wait_dict[item.id] = since, until - since = float(since) - max_wait = float(until-since) - rest = int(until-time()) - if rest < 0: - return 0, None - res = 100/max_wait - perc = rest*res - return perc, rest - return None - - def getProgress(self, item, locked=True): - """ - return download progress, locks by default - since it's used in already locked calls, - it provides an option to not lock - """ - if locked: - locker = QMutexLocker(self.mutex) - if isinstance(item, Link): - try: - if item.data["status"] == 0: - return 100 - return int(item.data["downloading"]["percent"]) - except: - return 0 - elif isinstance(item, Package): - count = len(item.children) - perc_sum = 0 - for child in item.children: - try: - if child.data["status"] == 0: #completed - perc_sum += 100 - perc_sum += int(child.data["downloading"]["percent"]) - except: - pass - if count == 0: - return 0 - return perc_sum/count - return 0 - - def getSpeed(self, item): - """ - calculate download speed - """ - if isinstance(item, Link): - if item.data["downloading"]: - return int(item.data["downloading"]["speed"]) - elif isinstance(item, Package): - count = len(item.children) - speed_sum = 0 - all_waiting = True - running = False - for child in item.children: - val = 0 - if child.data["downloading"]: - if not child.data["statusmsg"] == "waiting": - all_waiting = False - val = int(child.data["downloading"]["speed"]) - running = True - speed_sum += val - if count == 0 or not running or all_waiting: - return None - return speed_sum - return None - - def data(self, index, role=Qt.DisplayRole): - """ - return cell data - """ - if not index.isValid(): - return QVariant() - if role == Qt.DisplayRole: - if index.column() == 0: - return QVariant(index.internalPointer().data["name"]) - elif index.column() == 1: - item = index.internalPointer() - plugins = [] - if isinstance(item, Package): - for child in item.children: - if not child.data["plugin"] in plugins: - plugins.append(child.data["plugin"]) - else: - plugins.append(item.data["plugin"]) - return QVariant(", ".join(plugins)) - elif index.column() == 2: - item = index.internalPointer() - status = 0 - speed = self.getSpeed(item) - if isinstance(item, Package): - for child in item.children: - if child.data["status"] > status: - status = child.data["status"] - else: - status = item.data["status"] - - if speed is None or status == 7 or status == 10 or status == 5: - return QVariant(self.translateStatus(statusMapReverse[status])) - else: - return QVariant("%s (%s)" % (self.translateStatus(statusMapReverse[status]), formatSpeed(speed))) - elif index.column() == 3: - item = index.internalPointer() - if isinstance(item, Link): - if item.data["status"] == 0: #TODO needs change?? - #self.getProgress(item, False) == 100: - return QVariant(formatSize(item.data["size"])) - elif self.getProgress(item, False) == 0: - try: - return QVariant("%s / %s" % (formatSize(item.data["size"]-item.data["downloading"]["bleft"]), formatSize(item.data["size"]))) - except: - return QVariant("0 B / %s" % formatSize(item.data["size"])) - else: - try: - return QVariant("%s / %s" % (formatSize(item.data["size"]-item.data["downloading"]["bleft"]), formatSize(item.data["size"]))) - except: - return QVariant("? / %s" % formatSize(item.data["size"])) - else: - ms = 0 - cs = 0 - for c in item.children: - try: - s = c.data["downloading"]["size"] - except: - s = c.data["size"] - if c.data["downloading"]: - cs += s - c.data["downloading"]["bleft"] - elif self.getProgress(c, False) == 100: - cs += s - ms += s - if cs == 0 or cs == ms: - return QVariant(formatSize(ms)) - else: - return QVariant("%s / %s" % (formatSize(cs), formatSize(ms))) - elif index.column() == 4: - item = index.internalPointer() - if isinstance(item, Link): - if item.data["downloading"]: - return QVariant(item.data["downloading"]["format_eta"]) - elif role == Qt.EditRole: - if index.column() == 0: - return QVariant(index.internalPointer().data["name"]) - return QVariant() - - def flags(self, index): - """ - cell flags - """ - if index.column() == 0 and self.parent(index) == QModelIndex(): - return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled - return Qt.ItemIsSelectable | Qt.ItemIsEnabled - -class QueueView(CollectorView): - """ - view component for queue - """ - - def __init__(self, connector): - CollectorView.__init__(self, connector) - self.setModel(QueueModel(self, connector)) - - self.setColumnWidth(0, 300) - self.setColumnWidth(1, 100) - self.setColumnWidth(2, 140) - self.setColumnWidth(3, 180) - self.setColumnWidth(4, 70) - - self.setEditTriggers(QAbstractItemView.NoEditTriggers) - - self.delegate = QueueProgressBarDelegate(self, self.model()) - self.setItemDelegateForColumn(5, self.delegate) - -class QueueProgressBarDelegate(QItemDelegate): - """ - used to display a progressbar in the progress cell - """ - - def __init__(self, parent, queue): - QItemDelegate.__init__(self, parent) - self.queue = queue - - def paint(self, painter, option, index): - """ - paint the progressbar - """ - if not index.isValid(): - return - if index.column() == 5: - item = index.internalPointer() - w = self.queue.getWaitingProgress(item) - wait = None - if w: - progress = w[0] - wait = w[1] - else: - progress = self.queue.getProgress(item) - opts = QStyleOptionProgressBarV2() - opts.maximum = 100 - opts.minimum = 0 - opts.progress = progress - opts.rect = option.rect - opts.rect.setRight(option.rect.right()-1) - opts.rect.setHeight(option.rect.height()-1) - opts.textVisible = True - opts.textAlignment = Qt.AlignCenter - if not wait is None: - opts.text = QString(_("waiting %d seconds") % (wait,)) - else: - opts.text = QString.number(opts.progress) + "%" - QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter) - return - QItemDelegate.paint(self, painter, option, index) - diff --git a/module/gui/SettingsWidget.py b/module/gui/SettingsWidget.py deleted file mode 100644 index cd22a7b9e..000000000 --- a/module/gui/SettingsWidget.py +++ /dev/null @@ -1,202 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from sip import delete - - -class SettingsWidget(QWidget): - def __init__(self): - QWidget.__init__(self) - self.connector = None - self.sections = {} - self.psections = {} - self.data = None - self.pdata = None - self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) - - def setConnector(self, connector): - self.connector = connector - - def loadConfig(self): - if self.sections and self.psections: - self.data = self.connector.getConfig() - self.pdata = self.connector.getPluginConfig() - - self.reloadSection(self.sections, self.data) - self.reloadSection(self.psections, self.pdata) - - return - - if self.layout(): - delete(self.layout()) - - for s in self.sections.values()+self.psections.values(): - delete(s) - - self.sections = {} - self.setLayout(QVBoxLayout()) - self.clearConfig() - layout = self.layout() - layout.setSizeConstraint(QLayout.SetMinAndMaxSize) - - general = QTabWidget() - self.general = general - - plugins = QTabWidget() - self.plugins = plugins - - tab = QTabWidget() - self.tab = tab - - gw = QWidget() - gw.setLayout(QVBoxLayout()) - gw.layout().addWidget(self.general) - pw = QWidget() - pw.setLayout(QVBoxLayout()) - pw.layout().addWidget(self.plugins) - tab.addTab(gw, _("General")) - tab.addTab(pw, _("Plugins")) - - layout.addWidget(tab) - - self.data = self.connector.getConfig() - self.pdata = self.connector.getPluginConfig() - for k, section in self.data.iteritems(): - s = Section(section, general) - self.sections[k] = s - - for k, section in self.pdata.iteritems(): - s = Section(section, plugins, "plugin") - self.psections[k] = s - - rel = QPushButton(_("Reload")) - save = QPushButton(_("Save")) - - layout.addWidget(save) - - cont = QHBoxLayout() - cont.addWidget(rel) - cont.addWidget(save) - - layout.addLayout(cont) - - self.connect(save, SIGNAL("clicked()"), self.saveConfig) - self.connect(rel, SIGNAL("clicked()"), self.loadConfig) - - def clearConfig(self): - self.sections = {} - - def reloadSection(self, sections, pdata): - - for k, section in enumerate(pdata): - if k in sections: - widget = sections[k] - for item in section.items: - if item.name in widget.inputs: - i = widget.inputs[item.name] - - if item.type == "int": - i.setValue(int(item.value)) - elif not item.type.find(";") == -1: - i.setCurrentIndex(i.findText(item.value)) - elif item.type == "bool": - if True if item.value.lower() in ("1","true", "on", "an","yes") else False: - i.setCurrentIndex(0) - else: - i.setCurrentIndex(1) - else: - i.setText(item.value) - - - def saveConfig(self): - self.data = self.connector.getConfig() - self.pdata = self.connector.getPluginConfig() - - self.saveSection(self.sections, self.data) - self.saveSection(self.psections, self.pdata, "plugin") - - - def saveSection(self, sections, pdata, sec="core"): - for k, section in enumerate(pdata): - if k in sections: - widget = sections[k] - for item in section.items: - if item.name in widget.inputs: - i = widget.inputs[item.name] - - #TODO : unresolved reference: option - - if item.type == "int": - if i.value() != int(item.value): - self.connector.setConfigValue(k, option, i.value(), sec) - elif not item.type.find(";") == -1: - if i.currentText() != item.value: - self.connector.setConfigValue(k, option, i.currentText(), sec) - elif item.type == "bool": - if (True if item.value.lower() in ("1","true", "on", "an","yes") else False) ^ (not i.currentIndex()): - self.connector.setConfigValue(k, option, not i.currentIndex(), sec) - else: - if i.text() != item.value: - self.connector.setConfigValue(k, option, str(i.text()), sec) - -class Section(QGroupBox): - def __init__(self, data, parent, ctype="core"): - self.data = data - QGroupBox.__init__(self, data.description, parent) - self.labels = {} - self.inputs = {} - self.ctype = ctype - layout = QFormLayout(self) - self.setLayout(layout) - - sw = QWidget() - sw.setLayout(QVBoxLayout()) - sw.layout().addWidget(self) - - sa = QScrollArea() - sa.setWidgetResizable(True) - sa.setWidget(sw) - sa.setFrameShape(sa.NoFrame) - - parent.addTab(sa, data.description) - - for option in self.data.items: - if option.type == "int": - i = QSpinBox(self) - i.setMaximum(999999) - i.setValue(int(option.value)) - elif not option.type.find(";") == -1: - choices = option.type.split(";") - i = QComboBox(self) - i.addItems(choices) - i.setCurrentIndex(i.findText(option.value)) - elif option.type == "bool": - i = QComboBox(self) - i.addItem(_("Yes"), QVariant(True)) - i.addItem(_("No"), QVariant(False)) - if True if option.value.lower() in ("1","true", "on", "an","yes") else False: - i.setCurrentIndex(0) - else: - i.setCurrentIndex(1) - else: - i = QLineEdit(self) - i.setText(option.value) - layout.addRow(option.description, i) - layout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) diff --git a/module/gui/XMLParser.py b/module/gui/XMLParser.py deleted file mode 100644 index 5e3b7bf65..000000000 --- a/module/gui/XMLParser.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" -from __future__ import with_statement - -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from PyQt4.QtXml import * - -import os - -class XMLParser(): - def __init__(self, data, dfile=""): - self.mutex = QMutex() - self.mutex.lock() - self.xml = QDomDocument() - self.file = data - self.dfile = dfile - self.mutex.unlock() - self.loadData() - self.root = self.xml.documentElement() - - def loadData(self): - self.mutex.lock() - f = self.file - if not os.path.exists(f): - f = self.dfile - with open(f, 'r') as fh: - content = fh.read() - self.xml.setContent(content) - self.mutex.unlock() - - def saveData(self): - self.mutex.lock() - content = self.xml.toString() - with open(self.file, 'w') as fh: - fh.write(content) - self.mutex.unlock() - return content - - def parseNode(self, node, ret_type="list"): - if ret_type == "dict": - childNodes = {} - else: - childNodes = [] - child = node.firstChild() - while True: - n = child.toElement() - if n.isNull(): - break - else: - if ret_type == "dict": - childNodes[str(n.tagName())] = n - else: - childNodes.append(n) - child = child.nextSibling() - return childNodes diff --git a/module/gui/__init__.py b/module/gui/__init__.py deleted file mode 100644 index 8d1c8b69c..000000000 --- a/module/gui/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/module/gui/connector.py b/module/gui/connector.py deleted file mode 100644 index c16ccd08e..000000000 --- a/module/gui/connector.py +++ /dev/null @@ -1,165 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -SERVER_VERSION = "0.4.9" - -from time import sleep -from uuid import uuid4 as uuid - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -import socket - -from module.remote.thriftbackend.ThriftClient import ThriftClient, WrongLogin, NoSSL, NoConnection -from thrift.Thrift import TException - -class Connector(QObject): - """ - manages the connection to the pyload core via thrift - """ - - firstAttempt = True - - def __init__(self): - QObject.__init__(self) - self.mutex = QMutex() - self.connectionID = None - self.host = None - self.port = None - self.user = None - self.password = None - self.ssl = None - self.running = True - self.internal = False - self.proxy = self.Dummy() - - def setConnectionData(self, host, port, user, password, ssl=False): - """ - set connection data for connection attempt, called from slotConnect - """ - self.host = host - self.port = port - self.user = user - self.password = password - self.ssl = ssl - - def connectProxy(self): - """ - initialize thrift rpc client, - check for ssl, check auth, - setup dispatcher, - connect error signals, - check server version - """ - if self.internal: return True - - err = None - try: - client = ThriftClient(self.host, self.port, self.user, self.password) - except WrongLogin: - err = _("bad login credentials") - except NoSSL: - err = _("no ssl support") - except NoConnection: - err = _("can't connect to host") - if err: - if not Connector.firstAttempt: - self.emit(SIGNAL("errorBox"), err) - Connector.firstAttempt = False - return False - - self.proxy = DispatchRPC(self.mutex, client) - self.connect(self.proxy, SIGNAL("connectionLost"), self, SIGNAL("connectionLost")) - - server_version = self.proxy.getServerVersion() - self.connectionID = uuid().hex - - if not server_version == SERVER_VERSION: - self.emit(SIGNAL("errorBox"), _("server is version %(new)s client accepts version %(current)s") % { "new": server_version, "current": SERVER_VERSION}) - return False - - return True - - def __getattr__(self, attr): - """ - redirect rpc calls to dispatcher - """ - return getattr(self.proxy, attr) - - class Dummy(object): - """ - dummy rpc proxy, to prevent errors - """ - def __nonzero__(self): - return False - - def __getattr__(self, attr): - def dummy(*args, **kwargs): - return None - return dummy - -class DispatchRPC(QObject): - """ - wraps the thrift client, to catch critical exceptions (connection lost) - adds thread safety - """ - - def __init__(self, mutex, server): - QObject.__init__(self) - self.mutex = mutex - self.server = server - - def __getattr__(self, attr): - """ - redirect and wrap call in Wrapper instance, locks dispatcher - """ - self.mutex.lock() - self.fname = attr - f = self.Wrapper(getattr(self.server, attr), self.mutex, self) - return f - - class Wrapper(object): - """ - represents a rpc call - """ - - def __init__(self, f, mutex, dispatcher): - self.f = f - self.mutex = mutex - self.dispatcher = dispatcher - - def __call__(self, *args, **kwargs): - """ - instance is called, rpc is executed - exceptions are processed - finally dispatcher is unlocked - """ - lost = False - try: - return self.f(*args, **kwargs) - except socket.error: #necessary? - lost = True - except TException: - lost = True - finally: - self.mutex.unlock() - if lost: - from traceback import print_exc - print_exc() - self.dispatcher.emit(SIGNAL("connectionLost")) diff --git a/module/lib/BeautifulSoup.py b/module/lib/BeautifulSoup.py index 55567f588..7278215ca 100644 --- a/module/lib/BeautifulSoup.py +++ b/module/lib/BeautifulSoup.py @@ -79,8 +79,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE, DAMMIT. from __future__ import generators __author__ = "Leonard Richardson (leonardr@segfault.org)" -__version__ = "3.0.8.1" -__copyright__ = "Copyright (c) 2004-2010 Leonard Richardson" +__version__ = "3.2.1" +__copyright__ = "Copyright (c) 2004-2012 Leonard Richardson" __license__ = "New-style BSD" from sgmllib import SGMLParser, SGMLParseError @@ -114,6 +114,21 @@ class PageElement(object): """Contains the navigational information for some part of the page (either a tag or a piece of text)""" + def _invert(h): + "Cheap function to invert a hash." + i = {} + for k,v in h.items(): + i[v] = k + return i + + XML_ENTITIES_TO_SPECIAL_CHARS = { "apos" : "'", + "quot" : '"', + "amp" : "&", + "lt" : "<", + "gt" : ">" } + + XML_SPECIAL_CHARS_TO_ENTITIES = _invert(XML_ENTITIES_TO_SPECIAL_CHARS) + def setup(self, parent=None, previous=None): """Sets up the initial relations between this element and other elements.""" @@ -421,6 +436,16 @@ class PageElement(object): s = unicode(s) return s + BARE_AMPERSAND_OR_BRACKET = re.compile("([<>]|" + + "&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;)" + + ")") + + def _sub_entity(self, x): + """Used with a regular expression to substitute the + appropriate XML entity for an XML special character.""" + return "&" + self.XML_SPECIAL_CHARS_TO_ENTITIES[x.group(0)[0]] + ";" + + class NavigableString(unicode, PageElement): def __new__(cls, value): @@ -451,10 +476,12 @@ class NavigableString(unicode, PageElement): return str(self).decode(DEFAULT_OUTPUT_ENCODING) def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): + # Substitute outgoing XML entities. + data = self.BARE_AMPERSAND_OR_BRACKET.sub(self._sub_entity, self) if encoding: - return self.encode(encoding) + return data.encode(encoding) else: - return self + return data class CData(NavigableString): @@ -480,21 +507,6 @@ class Tag(PageElement): """Represents a found HTML tag with its attributes and contents.""" - def _invert(h): - "Cheap function to invert a hash." - i = {} - for k,v in h.items(): - i[v] = k - return i - - XML_ENTITIES_TO_SPECIAL_CHARS = { "apos" : "'", - "quot" : '"', - "amp" : "&", - "lt" : "<", - "gt" : ">" } - - XML_SPECIAL_CHARS_TO_ENTITIES = _invert(XML_ENTITIES_TO_SPECIAL_CHARS) - def _convertEntities(self, match): """Used in a call to re.sub to replace HTML, XML, and numeric entities with the appropriate Unicode characters. If HTML @@ -531,6 +543,8 @@ class Tag(PageElement): self.name = name if attrs is None: attrs = [] + elif isinstance(attrs, dict): + attrs = attrs.items() self.attrs = attrs self.contents = [] self.setup(parent, previous) @@ -679,15 +693,6 @@ class Tag(PageElement): def __unicode__(self): return self.__str__(None) - BARE_AMPERSAND_OR_BRACKET = re.compile("([<>]|" - + "&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;)" - + ")") - - def _sub_entity(self, x): - """Used with a regular expression to substitute the - appropriate XML entity for an XML special character.""" - return "&" + self.XML_SPECIAL_CHARS_TO_ENTITIES[x.group(0)[0]] + ";" - def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING, prettyPrint=False, indentLevel=0): """Returns a string or Unicode representation of this tag and @@ -1295,7 +1300,7 @@ class BeautifulStoneSoup(Tag, SGMLParser): """ nestingResetTriggers = self.NESTABLE_TAGS.get(name) - isNestable = nestingResetTriggers is not None + isNestable = nestingResetTriggers != None isResetNesting = self.RESET_NESTING_TAGS.has_key(name) popTo = None inclusive = True diff --git a/module/lib/Unzip.py b/module/lib/Unzip.py deleted file mode 100644 index f56fbe751..000000000 --- a/module/lib/Unzip.py +++ /dev/null @@ -1,50 +0,0 @@ -import zipfile -import os - -class Unzip: - def __init__(self): - pass - - def extract(self, file, dir): - if not dir.endswith(':') and not os.path.exists(dir): - os.mkdir(dir) - - zf = zipfile.ZipFile(file) - - # create directory structure to house files - self._createstructure(file, dir) - - # extract files to directory structure - for i, name in enumerate(zf.namelist()): - - if not name.endswith('/') and not name.endswith("config"): - print "extracting", name.replace("pyload/","") - outfile = open(os.path.join(dir, name.replace("pyload/","")), 'wb') - outfile.write(zf.read(name)) - outfile.flush() - outfile.close() - - def _createstructure(self, file, dir): - self._makedirs(self._listdirs(file), dir) - - def _makedirs(self, directories, basedir): - """ Create any directories that don't currently exist """ - for dir in directories: - curdir = os.path.join(basedir, dir) - if not os.path.exists(curdir): - os.mkdir(curdir) - - def _listdirs(self, file): - """ Grabs all the directories in the zip structure - This is necessary to create the structure before trying - to extract the file to it. """ - zf = zipfile.ZipFile(file) - - dirs = [] - - for name in zf.namelist(): - if name.endswith('/'): - dirs.append(name.replace("pyload/","")) - - dirs.sort() - return dirs diff --git a/module/lib/beaker/__init__.py b/module/lib/beaker/__init__.py index 792d60054..d07785c52 100644 --- a/module/lib/beaker/__init__.py +++ b/module/lib/beaker/__init__.py @@ -1 +1 @@ -# +__version__ = '1.6.4' diff --git a/module/lib/beaker/cache.py b/module/lib/beaker/cache.py index 4a96537ff..0ae96e020 100644 --- a/module/lib/beaker/cache.py +++ b/module/lib/beaker/cache.py @@ -1,156 +1,248 @@ -"""Cache object +"""This package contains the "front end" classes and functions +for Beaker caching. -The Cache object is used to manage a set of cache files and their -associated backend. The backends can be rotated on the fly by -specifying an alternate type when used. - -Advanced users can add new backends in beaker.backends +Included are the :class:`.Cache` and :class:`.CacheManager` classes, +as well as the function decorators :func:`.region_decorate`, +:func:`.region_invalidate`. """ - import warnings import beaker.container as container import beaker.util as util +from beaker.crypto.util import sha1 from beaker.exceptions import BeakerException, InvalidCacheBackendError +from beaker.synchronization import _threading import beaker.ext.memcached as memcached import beaker.ext.database as database import beaker.ext.sqla as sqla import beaker.ext.google as google -# Initialize the basic available backends -clsmap = { - 'memory':container.MemoryNamespaceManager, - 'dbm':container.DBMNamespaceManager, - 'file':container.FileNamespaceManager, - 'ext:memcached':memcached.MemcachedNamespaceManager, - 'ext:database':database.DatabaseNamespaceManager, - 'ext:sqla': sqla.SqlaNamespaceManager, - 'ext:google': google.GoogleNamespaceManager, - } - # Initialize the cache region dict cache_regions = {} +"""Dictionary of 'region' arguments. + +A "region" is a string name that refers to a series of cache +configuration arguments. An application may have multiple +"regions" - one which stores things in a memory cache, one +which writes data to files, etc. + +The dictionary stores string key names mapped to dictionaries +of configuration arguments. Example:: + + from beaker.cache import cache_regions + cache_regions.update({ + 'short_term':{ + 'expire':'60', + 'type':'memory' + }, + 'long_term':{ + 'expire':'1800', + 'type':'dbm', + 'data_dir':'/tmp', + } + }) +""" + + cache_managers = {} -try: - import pkg_resources - # Load up the additional entry point defined backends - for entry_point in pkg_resources.iter_entry_points('beaker.backends'): +class _backends(object): + initialized = False + + def __init__(self, clsmap): + self._clsmap = clsmap + self._mutex = _threading.Lock() + + def __getitem__(self, key): try: - NamespaceManager = entry_point.load() - name = entry_point.name - if name in clsmap: - raise BeakerException("NamespaceManager name conflict,'%s' " - "already loaded" % name) - clsmap[name] = NamespaceManager - except (InvalidCacheBackendError, SyntaxError): - # Ignore invalid backends + return self._clsmap[key] + except KeyError, e: + if not self.initialized: + self._mutex.acquire() + try: + if not self.initialized: + self._init() + self.initialized = True + + return self._clsmap[key] + finally: + self._mutex.release() + + raise e + + def _init(self): + try: + import pkg_resources + + # Load up the additional entry point defined backends + for entry_point in pkg_resources.iter_entry_points('beaker.backends'): + try: + namespace_manager = entry_point.load() + name = entry_point.name + if name in self._clsmap: + raise BeakerException("NamespaceManager name conflict,'%s' " + "already loaded" % name) + self._clsmap[name] = namespace_manager + except (InvalidCacheBackendError, SyntaxError): + # Ignore invalid backends + pass + except: + import sys + from pkg_resources import DistributionNotFound + # Warn when there's a problem loading a NamespaceManager + if not isinstance(sys.exc_info()[1], DistributionNotFound): + import traceback + from StringIO import StringIO + tb = StringIO() + traceback.print_exc(file=tb) + warnings.warn( + "Unable to load NamespaceManager " + "entry point: '%s': %s" % ( + entry_point, + tb.getvalue()), + RuntimeWarning, 2) + except ImportError: pass - except: - import sys - from pkg_resources import DistributionNotFound - # Warn when there's a problem loading a NamespaceManager - if not isinstance(sys.exc_info()[1], DistributionNotFound): - import traceback - from StringIO import StringIO - tb = StringIO() - traceback.print_exc(file=tb) - warnings.warn("Unable to load NamespaceManager entry point: '%s': " - "%s" % (entry_point, tb.getvalue()), RuntimeWarning, - 2) -except ImportError: - pass - - - - -def cache_region(region, *deco_args): - """Decorate a function to cache itself using a cache region - - The region decorator requires arguments if there are more than - 2 of the same named function, in the same module. This is - because the namespace used for the functions cache is based on - the functions name and the module. - - + +# Initialize the basic available backends +clsmap = _backends({ + 'memory': container.MemoryNamespaceManager, + 'dbm': container.DBMNamespaceManager, + 'file': container.FileNamespaceManager, + 'ext:memcached': memcached.MemcachedNamespaceManager, + 'ext:database': database.DatabaseNamespaceManager, + 'ext:sqla': sqla.SqlaNamespaceManager, + 'ext:google': google.GoogleNamespaceManager, + }) + + +def cache_region(region, *args): + """Decorate a function such that its return result is cached, + using a "region" to indicate the cache arguments. + Example:: - - # Add cache region settings to beaker: - beaker.cache.cache_regions.update(dict_of_config_region_options)) - - @cache_region('short_term', 'some_data') - def populate_things(search_term, limit, offset): - return load_the_data(search_term, limit, offset) - - return load('rabbits', 20, 0) - + + from beaker.cache import cache_regions, cache_region + + # configure regions + cache_regions.update({ + 'short_term':{ + 'expire':'60', + 'type':'memory' + } + }) + + @cache_region('short_term', 'load_things') + def load(search_term, limit, offset): + '''Load from a database given a search term, limit, offset.''' + return database.query(search_term)[offset:offset + limit] + + The decorator can also be used with object methods. The ``self`` + argument is not part of the cache key. This is based on the + actual string name ``self`` being in the first argument + position (new in 1.6):: + + class MyThing(object): + @cache_region('short_term', 'load_things') + def load(self, search_term, limit, offset): + '''Load from a database given a search term, limit, offset.''' + return database.query(search_term)[offset:offset + limit] + + Classmethods work as well - use ``cls`` as the name of the class argument, + and place the decorator around the function underneath ``@classmethod`` + (new in 1.6):: + + class MyThing(object): + @classmethod + @cache_region('short_term', 'load_things') + def load(cls, search_term, limit, offset): + '''Load from a database given a search term, limit, offset.''' + return database.query(search_term)[offset:offset + limit] + + :param region: String name of the region corresponding to the desired + caching arguments, established in :attr:`.cache_regions`. + + :param \*args: Optional ``str()``-compatible arguments which will uniquely + identify the key used by this decorated function, in addition + to the positional arguments passed to the function itself at call time. + This is recommended as it is needed to distinguish between any two functions + or methods that have the same name (regardless of parent class or not). + .. note:: - + The function being decorated must only be called with - positional arguments. - + positional arguments, and the arguments must support + being stringified with ``str()``. The concatenation + of the ``str()`` version of each argument, combined + with that of the ``*args`` sent to the decorator, + forms the unique cache key. + + .. note:: + + When a method on a class is decorated, the ``self`` or ``cls`` + argument in the first position is + not included in the "key" used for caching. New in 1.6. + """ - cache = [None] - - def decorate(func): - namespace = util.func_namespace(func) - def cached(*args): - reg = cache_regions[region] - if not reg.get('enabled', True): - return func(*args) - - if not cache[0]: - if region not in cache_regions: - raise BeakerException('Cache region not configured: %s' % region) - cache[0] = Cache._get_cache(namespace, reg) - - cache_key = " ".join(map(str, deco_args + args)) - def go(): - return func(*args) - - return cache[0].get_value(cache_key, createfunc=go) - cached._arg_namespace = namespace - cached._arg_region = region - return cached - return decorate + return _cache_decorate(args, None, None, region) def region_invalidate(namespace, region, *args): - """Invalidate a cache region namespace or decorated function - - This function only invalidates cache spaces created with the - cache_region decorator. - - :param namespace: Either the namespace of the result to invalidate, or the - cached function reference - - :param region: The region the function was cached to. If the function was - cached to a single region then this argument can be None - - :param args: Arguments that were used to differentiate the cached - function as well as the arguments passed to the decorated - function + """Invalidate a cache region corresponding to a function + decorated with :func:`.cache_region`. + + :param namespace: The namespace of the cache to invalidate. This is typically + a reference to the original function (as returned by the :func:`.cache_region` + decorator), where the :func:`.cache_region` decorator applies a "memo" to + the function in order to locate the string name of the namespace. + + :param region: String name of the region used with the decorator. This can be + ``None`` in the usual case that the decorated function itself is passed, + not the string name of the namespace. + + :param args: Stringifyable arguments that are used to locate the correct + key. This consists of the ``*args`` sent to the :func:`.cache_region` + decorator itself, plus the ``*args`` sent to the function itself + at runtime. Example:: - - # Add cache region settings to beaker: - beaker.cache.cache_regions.update(dict_of_config_region_options)) - - def populate_things(invalidate=False): - + + from beaker.cache import cache_regions, cache_region, region_invalidate + + # configure regions + cache_regions.update({ + 'short_term':{ + 'expire':'60', + 'type':'memory' + } + }) + + @cache_region('short_term', 'load_data') + def load(search_term, limit, offset): + '''Load from a database given a search term, limit, offset.''' + return database.query(search_term)[offset:offset + limit] + + def invalidate_search(search_term, limit, offset): + '''Invalidate the cached storage for a given search term, limit, offset.''' + region_invalidate(load, 'short_term', 'load_data', search_term, limit, offset) + + Note that when a method on a class is decorated, the first argument ``cls`` + or ``self`` is not included in the cache key. This means you don't send + it to :func:`.region_invalidate`:: + + class MyThing(object): @cache_region('short_term', 'some_data') - def load(search_term, limit, offset): - return load_the_data(search_term, limit, offset) - - # If the results should be invalidated first - if invalidate: - region_invalidate(load, None, 'some_data', - 'rabbits', 20, 0) - return load('rabbits', 20, 0) - + def load(self, search_term, limit, offset): + '''Load from a database given a search term, limit, offset.''' + return database.query(search_term)[offset:offset + limit] + + def invalidate_search(self, search_term, limit, offset): + '''Invalidate the cached storage for a given search term, limit, offset.''' + region_invalidate(self.load, 'short_term', 'some_data', search_term, limit, offset) + """ if callable(namespace): if not region: @@ -162,10 +254,9 @@ def region_invalidate(namespace, region, *args): "namespace is required") else: region = cache_regions[region] - + cache = Cache._get_cache(namespace, region) - cache_key = " ".join(str(x) for x in args) - cache.remove_value(cache_key) + _cache_decorator_invalidate(cache, region['key_length'], args) class Cache(object): @@ -180,7 +271,7 @@ class Cache(object): :param expiretime: seconds to keep cached data (legacy support) :param starttime: time when cache was cache was - + """ def __init__(self, namespace, type='memory', expiretime=None, starttime=None, expire=None, **nsargs): @@ -190,12 +281,12 @@ class Cache(object): raise cls except KeyError: raise TypeError("Unknown cache implementation %r" % type) - + self.namespace_name = namespace self.namespace = cls(namespace, **nsargs) self.expiretime = expiretime or expire self.starttime = starttime self.nsargs = nsargs - + @classmethod def _get_cache(cls, namespace, kw): key = namespace + str(kw) @@ -204,20 +295,19 @@ class Cache(object): except KeyError: cache_managers[key] = cache = cls(namespace, **kw) return cache - + def put(self, key, value, **kw): self._get_value(key, **kw).set_value(value) set_value = put - + def get(self, key, **kw): """Retrieve a cached value from the container""" return self._get_value(key, **kw).get_value() get_value = get - + def remove_value(self, key, **kw): mycontainer = self._get_value(key, **kw) - if mycontainer.has_current_value(): - mycontainer.clear_value() + mycontainer.clear_value() remove = remove_value def _get_value(self, key, **kw): @@ -229,9 +319,9 @@ class Cache(object): kw.setdefault('expiretime', self.expiretime) kw.setdefault('starttime', self.starttime) - + return container.Value(key, self.namespace, **kw) - + @util.deprecated("Specifying a " "'type' and other namespace configuration with cache.get()/put()/etc. " "is deprecated. Specify 'type' and other namespace configuration to " @@ -243,26 +333,26 @@ class Cache(object): kwargs = self.nsargs.copy() kwargs.update(kw) c = Cache(self.namespace.namespace, type=type, **kwargs) - return c._get_value(key, expiretime=expiretime, createfunc=createfunc, + return c._get_value(key, expiretime=expiretime, createfunc=createfunc, starttime=starttime) - + def clear(self): """Clear all the values from the namespace""" self.namespace.remove() - + # dict interface def __getitem__(self, key): return self.get(key) - + def __contains__(self, key): return self._get_value(key).has_current_value() - + def has_key(self, key): return key in self - + def __delitem__(self, key): self.remove_value(key) - + def __setitem__(self, key, value): self.put(key, value) @@ -270,110 +360,96 @@ class Cache(object): class CacheManager(object): def __init__(self, **kwargs): """Initialize a CacheManager object with a set of options - + Options should be parsed with the :func:`~beaker.util.parse_cache_config_options` function to ensure only valid options are used. - + """ self.kwargs = kwargs self.regions = kwargs.pop('cache_regions', {}) - + # Add these regions to the module global cache_regions.update(self.regions) - + def get_cache(self, name, **kwargs): kw = self.kwargs.copy() kw.update(kwargs) return Cache._get_cache(name, kw) - + def get_cache_region(self, name, region): if region not in self.regions: raise BeakerException('Cache region not configured: %s' % region) kw = self.regions[region] return Cache._get_cache(name, kw) - + def region(self, region, *args): """Decorate a function to cache itself using a cache region - + The region decorator requires arguments if there are more than - 2 of the same named function, in the same module. This is + two of the same named function, in the same module. This is because the namespace used for the functions cache is based on the functions name and the module. - - + + Example:: - + # Assuming a cache object is available like: cache = CacheManager(dict_of_config_options) - - + + def populate_things(): - + @cache.region('short_term', 'some_data') def load(search_term, limit, offset): return load_the_data(search_term, limit, offset) - + return load('rabbits', 20, 0) - + .. note:: - + The function being decorated must only be called with positional arguments. - + """ return cache_region(region, *args) def region_invalidate(self, namespace, region, *args): """Invalidate a cache region namespace or decorated function - + This function only invalidates cache spaces created with the cache_region decorator. - + :param namespace: Either the namespace of the result to invalidate, or the - name of the cached function - + cached function + :param region: The region the function was cached to. If the function was cached to a single region then this argument can be None - + :param args: Arguments that were used to differentiate the cached function as well as the arguments passed to the decorated function Example:: - + # Assuming a cache object is available like: cache = CacheManager(dict_of_config_options) - + def populate_things(invalidate=False): - + @cache.region('short_term', 'some_data') def load(search_term, limit, offset): return load_the_data(search_term, limit, offset) - + # If the results should be invalidated first if invalidate: cache.region_invalidate(load, None, 'some_data', 'rabbits', 20, 0) return load('rabbits', 20, 0) - - + + """ return region_invalidate(namespace, region, *args) - if callable(namespace): - if not region: - region = namespace._arg_region - namespace = namespace._arg_namespace - - if not region: - raise BeakerException("Region or callable function " - "namespace is required") - else: - region = self.regions[region] - - cache = self.get_cache(namespace, **region) - cache_key = " ".join(str(x) for x in args) - cache.remove_value(cache_key) def cache(self, *args, **kwargs): """Decorate a function to cache itself with supplied parameters @@ -387,46 +463,32 @@ class CacheManager(object): # Assuming a cache object is available like: cache = CacheManager(dict_of_config_options) - - + + def populate_things(): - + @cache.cache('mycache', expire=15) def load(search_term, limit, offset): return load_the_data(search_term, limit, offset) - + return load('rabbits', 20, 0) - + .. note:: - + The function being decorated must only be called with - positional arguments. + positional arguments. """ - cache = [None] - key = " ".join(str(x) for x in args) - - def decorate(func): - namespace = util.func_namespace(func) - def cached(*args): - if not cache[0]: - cache[0] = self.get_cache(namespace, **kwargs) - cache_key = key + " " + " ".join(str(x) for x in args) - def go(): - return func(*args) - return cache[0].get_value(cache_key, createfunc=go) - cached._arg_namespace = namespace - return cached - return decorate + return _cache_decorate(args, self, kwargs, None) def invalidate(self, func, *args, **kwargs): """Invalidate a cache decorated function - + This function only invalidates cache spaces created with the cache decorator. - + :param func: Decorated function to invalidate - + :param args: Used to make the key unique for this function, as in region() above. @@ -435,25 +497,93 @@ class CacheManager(object): function Example:: - + # Assuming a cache object is available like: cache = CacheManager(dict_of_config_options) - - + + def populate_things(invalidate=False): - + @cache.cache('mycache', type="file", expire=15) def load(search_term, limit, offset): return load_the_data(search_term, limit, offset) - + # If the results should be invalidated first if invalidate: cache.invalidate(load, 'mycache', 'rabbits', 20, 0, type="file") return load('rabbits', 20, 0) - + """ namespace = func._arg_namespace cache = self.get_cache(namespace, **kwargs) - cache_key = " ".join(str(x) for x in args) - cache.remove_value(cache_key) + if hasattr(func, '_arg_region'): + key_length = cache_regions[func._arg_region]['key_length'] + else: + key_length = kwargs.pop('key_length', 250) + _cache_decorator_invalidate(cache, key_length, args) + + +def _cache_decorate(deco_args, manager, kwargs, region): + """Return a caching function decorator.""" + + cache = [None] + + def decorate(func): + namespace = util.func_namespace(func) + skip_self = util.has_self_arg(func) + + def cached(*args): + if not cache[0]: + if region is not None: + if region not in cache_regions: + raise BeakerException( + 'Cache region not configured: %s' % region) + reg = cache_regions[region] + if not reg.get('enabled', True): + return func(*args) + cache[0] = Cache._get_cache(namespace, reg) + elif manager: + cache[0] = manager.get_cache(namespace, **kwargs) + else: + raise Exception("'manager + kwargs' or 'region' " + "argument is required") + + if skip_self: + try: + cache_key = " ".join(map(str, deco_args + args[1:])) + except UnicodeEncodeError: + cache_key = " ".join(map(unicode, deco_args + args[1:])) + else: + try: + cache_key = " ".join(map(str, deco_args + args)) + except UnicodeEncodeError: + cache_key = " ".join(map(unicode, deco_args + args)) + if region: + key_length = cache_regions[region]['key_length'] + else: + key_length = kwargs.pop('key_length', 250) + if len(cache_key) + len(namespace) > int(key_length): + cache_key = sha1(cache_key).hexdigest() + + def go(): + return func(*args) + + return cache[0].get_value(cache_key, createfunc=go) + cached._arg_namespace = namespace + if region is not None: + cached._arg_region = region + return cached + return decorate + + +def _cache_decorator_invalidate(cache, key_length, args): + """Invalidate a cache key based on function arguments.""" + + try: + cache_key = " ".join(map(str, args)) + except UnicodeEncodeError: + cache_key = " ".join(map(unicode, args)) + if len(cache_key) + len(cache.namespace_name) > key_length: + cache_key = sha1(cache_key).hexdigest() + cache.remove_value(cache_key) diff --git a/module/lib/beaker/container.py b/module/lib/beaker/container.py index 515e97af6..5a2e8e75c 100644 --- a/module/lib/beaker/container.py +++ b/module/lib/beaker/container.py @@ -1,11 +1,18 @@ """Container and Namespace classes""" -import anydbm + +import beaker.util as util +if util.py3k: + try: + import dbm as anydbm + except: + import dumbdbm as anydbm +else: + import anydbm import cPickle import logging import os import time -import beaker.util as util from beaker.exceptions import CreationAbortedError, MissingCacheParameter from beaker.synchronization import _threading, file_synchronizer, \ mutex_synchronizer, NameLock, null_synchronizer @@ -28,88 +35,162 @@ else: class NamespaceManager(object): """Handles dictionary operations and locking for a namespace of values. - + + :class:`.NamespaceManager` provides a dictionary-like interface, + implementing ``__getitem__()``, ``__setitem__()``, and + ``__contains__()``, as well as functions related to lock + acquisition. + The implementation for setting and retrieving the namespace data is handled by subclasses. - - NamespaceManager may be used alone, or may be privately accessed by - one or more Container objects. Container objects provide per-key + + NamespaceManager may be used alone, or may be accessed by + one or more :class:`.Value` objects. :class:`.Value` objects provide per-key services like expiration times and automatic recreation of values. - + Multiple NamespaceManagers created with a particular name will all share access to the same underlying datasource and will attempt to synchronize against a common mutex object. The scope of this sharing may be within a single process or across multiple processes, depending on the type of NamespaceManager used. - + The NamespaceManager itself is generally threadsafe, except in the case of the DBMNamespaceManager in conjunction with the gdbm dbm implementation. """ - + @classmethod def _init_dependencies(cls): - pass - + """Initialize module-level dependent libraries required + by this :class:`.NamespaceManager`.""" + def __init__(self, namespace): self._init_dependencies() self.namespace = namespace - + def get_creation_lock(self, key): + """Return a locking object that is used to synchronize + multiple threads or processes which wish to generate a new + cache value. + + This function is typically an instance of + :class:`.FileSynchronizer`, :class:`.ConditionSynchronizer`, + or :class:`.null_synchronizer`. + + The creation lock is only used when a requested value + does not exist, or has been expired, and is only used + by the :class:`.Value` key-management object in conjunction + with a "createfunc" value-creation function. + + """ raise NotImplementedError() def do_remove(self): + """Implement removal of the entire contents of this + :class:`.NamespaceManager`. + + e.g. for a file-based namespace, this would remove + all the files. + + The front-end to this method is the + :meth:`.NamespaceManager.remove` method. + + """ raise NotImplementedError() def acquire_read_lock(self): - pass + """Establish a read lock. + + This operation is called before a key is read. By + default the function does nothing. + + """ def release_read_lock(self): - pass + """Release a read lock. + + This operation is called after a key is read. By + default the function does nothing. + + """ + + def acquire_write_lock(self, wait=True, replace=False): + """Establish a write lock. + + This operation is called before a key is written. + A return value of ``True`` indicates the lock has + been acquired. - def acquire_write_lock(self, wait=True): + By default the function returns ``True`` unconditionally. + + 'replace' is a hint indicating the full contents + of the namespace may be safely discarded. Some backends + may implement this (i.e. file backend won't unpickle the + current contents). + + """ return True def release_write_lock(self): - pass + """Release a write lock. + + This operation is called after a new value is written. + By default this function does nothing. + + """ def has_key(self, key): + """Return ``True`` if the given key is present in this + :class:`.Namespace`. + """ return self.__contains__(key) def __getitem__(self, key): raise NotImplementedError() - + def __setitem__(self, key, value): raise NotImplementedError() - + def set_value(self, key, value, expiretime=None): - """Optional set_value() method called by Value. - - Allows an expiretime to be passed, for namespace - implementations which can prune their collections - using expiretime. - + """Sets a value in this :class:`.NamespaceManager`. + + This is the same as ``__setitem__()``, but + also allows an expiration time to be passed + at the same time. + """ self[key] = value - + def __contains__(self, key): raise NotImplementedError() def __delitem__(self, key): raise NotImplementedError() - + def keys(self): + """Return the list of all keys. + + This method may not be supported by all + :class:`.NamespaceManager` implementations. + + """ raise NotImplementedError() - + def remove(self): + """Remove the entire contents of this + :class:`.NamespaceManager`. + + e.g. for a file-based namespace, this would remove + all the files. + """ self.do_remove() - + class OpenResourceNamespaceManager(NamespaceManager): """A NamespaceManager where read/write operations require opening/ closing of a resource which is possibly mutexed. - + """ def __init__(self, namespace): NamespaceManager.__init__(self, namespace) @@ -120,51 +201,51 @@ class OpenResourceNamespaceManager(NamespaceManager): def get_access_lock(self): raise NotImplementedError() - def do_open(self, flags): + def do_open(self, flags, replace): raise NotImplementedError() - def do_close(self): + def do_close(self): raise NotImplementedError() - def acquire_read_lock(self): + def acquire_read_lock(self): self.access_lock.acquire_read_lock() try: - self.open('r', checkcount = True) + self.open('r', checkcount=True) except: self.access_lock.release_read_lock() raise - + def release_read_lock(self): try: - self.close(checkcount = True) + self.close(checkcount=True) finally: self.access_lock.release_read_lock() - - def acquire_write_lock(self, wait=True): + + def acquire_write_lock(self, wait=True, replace=False): r = self.access_lock.acquire_write_lock(wait) try: - if (wait or r): - self.open('c', checkcount = True) + if (wait or r): + self.open('c', checkcount=True, replace=replace) return r except: self.access_lock.release_write_lock() raise - - def release_write_lock(self): + + def release_write_lock(self): try: self.close(checkcount=True) finally: self.access_lock.release_write_lock() - def open(self, flags, checkcount=False): + def open(self, flags, checkcount=False, replace=False): self.mutex.acquire() try: if checkcount: - if self.openers == 0: - self.do_open(flags) + if self.openers == 0: + self.do_open(flags, replace) self.openers += 1 else: - self.do_open(flags) + self.do_open(flags, replace) self.openers = 1 finally: self.mutex.release() @@ -174,7 +255,7 @@ class OpenResourceNamespaceManager(NamespaceManager): try: if checkcount: self.openers -= 1 - if self.openers == 0: + if self.openers == 0: self.do_close() else: if self.openers > 0: @@ -191,7 +272,13 @@ class OpenResourceNamespaceManager(NamespaceManager): finally: self.access_lock.release_write_lock() + class Value(object): + """Implements synchronization, expiration, and value-creation logic + for a single value stored in a :class:`.NamespaceManager`. + + """ + __slots__ = 'key', 'createfunc', 'expiretime', 'expire_argument', 'starttime', 'storedtime',\ 'namespace' @@ -210,18 +297,18 @@ class Value(object): """ self.namespace.acquire_read_lock() - try: - return self.namespace.has_key(self.key) + try: + return self.key in self.namespace finally: self.namespace.release_read_lock() def can_have_value(self): - return self.has_current_value() or self.createfunc is not None + return self.has_current_value() or self.createfunc is not None def has_current_value(self): self.namespace.acquire_read_lock() - try: - has_value = self.namespace.has_key(self.key) + try: + has_value = self.key in self.namespace if has_value: try: stored, expired, value = self._get_value() @@ -258,7 +345,7 @@ class Value(object): except KeyError: # guard against un-mutexed backends raising KeyError has_value = False - + if not self.createfunc: raise KeyError(self.key) finally: @@ -317,10 +404,10 @@ class Value(object): self.set_value(value, stored) self.namespace.acquire_read_lock() except TypeError: - # occurs when the value is None. memcached - # may yank the rug from under us in which case + # occurs when the value is None. memcached + # may yank the rug from under us in which case # that's the result - raise KeyError(self.key) + raise KeyError(self.key) return stored, expired, value def set_value(self, value, storedtime=None): @@ -337,7 +424,7 @@ class Value(object): self.namespace.acquire_write_lock() try: debug("clear_value") - if self.namespace.has_key(self.key): + if self.key in self.namespace: try: del self.namespace[self.key] except KeyError: @@ -347,71 +434,80 @@ class Value(object): finally: self.namespace.release_write_lock() + class AbstractDictionaryNSManager(NamespaceManager): """A subclassable NamespaceManager that places data in a dictionary. - + Subclasses should provide a "dictionary" attribute or descriptor which returns a dict-like object. The dictionary will store keys that are local to the "namespace" attribute of this manager, so ensure that the dictionary will not be used by any other namespace. e.g.:: - + import collections cached_data = collections.defaultdict(dict) - + class MyDictionaryManager(AbstractDictionaryNSManager): def __init__(self, namespace): AbstractDictionaryNSManager.__init__(self, namespace) self.dictionary = cached_data[self.namespace] - + The above stores data in a global dictionary called "cached_data", which is structured as a dictionary of dictionaries, keyed first on namespace name to a sub-dictionary, then on actual cache key to value. - + """ - + def get_creation_lock(self, key): return NameLock( - identifier="memorynamespace/funclock/%s/%s" % (self.namespace, key), + identifier="memorynamespace/funclock/%s/%s" % + (self.namespace, key), reentrant=True ) - def __getitem__(self, key): + def __getitem__(self, key): return self.dictionary[key] - def __contains__(self, key): + def __contains__(self, key): return self.dictionary.__contains__(key) - def has_key(self, key): + def has_key(self, key): return self.dictionary.__contains__(key) - + def __setitem__(self, key, value): self.dictionary[key] = value - + def __delitem__(self, key): del self.dictionary[key] def do_remove(self): self.dictionary.clear() - + def keys(self): return self.dictionary.keys() - + + class MemoryNamespaceManager(AbstractDictionaryNSManager): + """:class:`.NamespaceManager` that uses a Python dictionary for storage.""" + namespaces = util.SyncDict() def __init__(self, namespace, **kwargs): AbstractDictionaryNSManager.__init__(self, namespace) - self.dictionary = MemoryNamespaceManager.namespaces.get(self.namespace, - dict) + self.dictionary = MemoryNamespaceManager.\ + namespaces.get(self.namespace, dict) + class DBMNamespaceManager(OpenResourceNamespaceManager): - def __init__(self, namespace, dbmmodule=None, data_dir=None, - dbm_dir=None, lock_dir=None, digest_filenames=True, **kwargs): + """:class:`.NamespaceManager` that uses ``dbm`` files for storage.""" + + def __init__(self, namespace, dbmmodule=None, data_dir=None, + dbm_dir=None, lock_dir=None, + digest_filenames=True, **kwargs): self.digest_filenames = digest_filenames - + if not dbm_dir and not data_dir: raise MissingCacheParameter("data_dir or dbm_dir is required") elif dbm_dir: @@ -419,7 +515,7 @@ class DBMNamespaceManager(OpenResourceNamespaceManager): else: self.dbm_dir = data_dir + "/container_dbm" util.verify_directory(self.dbm_dir) - + if not lock_dir and not data_dir: raise MissingCacheParameter("data_dir or lock_dir is required") elif lock_dir: @@ -433,50 +529,52 @@ class DBMNamespaceManager(OpenResourceNamespaceManager): self.dbm = None OpenResourceNamespaceManager.__init__(self, namespace) - self.file = util.encoded_path(root= self.dbm_dir, + self.file = util.encoded_path(root=self.dbm_dir, identifiers=[self.namespace], extension='.dbm', digest_filenames=self.digest_filenames) - + debug("data file %s", self.file) self._checkfile() def get_access_lock(self): return file_synchronizer(identifier=self.namespace, lock_dir=self.lock_dir) - + def get_creation_lock(self, key): return file_synchronizer( - identifier = "dbmcontainer/funclock/%s" % self.namespace, + identifier="dbmcontainer/funclock/%s/%s" % ( + self.namespace, key + ), lock_dir=self.lock_dir ) def file_exists(self, file): - if os.access(file, os.F_OK): + if os.access(file, os.F_OK): return True else: for ext in ('db', 'dat', 'pag', 'dir'): if os.access(file + os.extsep + ext, os.F_OK): return True - + return False - + def _checkfile(self): if not self.file_exists(self.file): - g = self.dbmmodule.open(self.file, 'c') + g = self.dbmmodule.open(self.file, 'c') g.close() - + def get_filenames(self): list = [] if os.access(self.file, os.F_OK): list.append(self.file) - + for ext in ('pag', 'dir', 'db', 'dat'): if os.access(self.file + os.extsep + ext, os.F_OK): list.append(self.file + os.extsep + ext) return list - def do_open(self, flags): + def do_open(self, flags, replace): debug("opening dbm file %s", self.file) try: self.dbm = self.dbmmodule.open(self.file, flags) @@ -488,17 +586,17 @@ class DBMNamespaceManager(OpenResourceNamespaceManager): if self.dbm is not None: debug("closing dbm file %s", self.file) self.dbm.close() - + def do_remove(self): for f in self.get_filenames(): os.remove(f) - - def __getitem__(self, key): + + def __getitem__(self, key): return cPickle.loads(self.dbm[key]) - def __contains__(self, key): - return self.dbm.has_key(key) - + def __contains__(self, key): + return key in self.dbm + def __setitem__(self, key, value): self.dbm[key] = cPickle.dumps(value) @@ -510,10 +608,17 @@ class DBMNamespaceManager(OpenResourceNamespaceManager): class FileNamespaceManager(OpenResourceNamespaceManager): + """:class:`.NamespaceManager` that uses binary files for storage. + + Each namespace is implemented as a single file storing a + dictionary of key/value pairs, serialized using the Python + ``pickle`` module. + + """ def __init__(self, namespace, data_dir=None, file_dir=None, lock_dir=None, digest_filenames=True, **kwargs): self.digest_filenames = digest_filenames - + if not file_dir and not data_dir: raise MissingCacheParameter("data_dir or file_dir is required") elif file_dir: @@ -531,38 +636,37 @@ class FileNamespaceManager(OpenResourceNamespaceManager): util.verify_directory(self.lock_dir) OpenResourceNamespaceManager.__init__(self, namespace) - self.file = util.encoded_path(root=self.file_dir, + self.file = util.encoded_path(root=self.file_dir, identifiers=[self.namespace], extension='.cache', digest_filenames=self.digest_filenames) self.hash = {} - + debug("data file %s", self.file) def get_access_lock(self): return file_synchronizer(identifier=self.namespace, lock_dir=self.lock_dir) - + def get_creation_lock(self, key): return file_synchronizer( - identifier = "filecontainer/funclock/%s" % self.namespace, - lock_dir = self.lock_dir + identifier="dbmcontainer/funclock/%s/%s" % ( + self.namespace, key + ), + lock_dir=self.lock_dir ) - + def file_exists(self, file): return os.access(file, os.F_OK) - def do_open(self, flags): - if self.file_exists(self.file): + def do_open(self, flags, replace): + if not replace and self.file_exists(self.file): fh = open(self.file, 'rb') - try: - self.hash = cPickle.load(fh) - except (IOError, OSError, EOFError, cPickle.PickleError, ValueError): - pass + self.hash = cPickle.load(fh) fh.close() self.flags = flags - + def do_close(self): if self.flags == 'c' or self.flags == 'w': fh = open(self.file, 'wb') @@ -571,22 +675,22 @@ class FileNamespaceManager(OpenResourceNamespaceManager): self.hash = {} self.flags = None - + def do_remove(self): try: os.remove(self.file) - except OSError, err: + except OSError: # for instance, because we haven't yet used this cache, # but client code has asked for a clear() operation... pass self.hash = {} - - def __getitem__(self, key): + + def __getitem__(self, key): return self.hash[key] - def __contains__(self, key): - return self.hash.has_key(key) - + def __contains__(self, key): + return key in self.hash + def __setitem__(self, key, value): self.hash[key] = value @@ -602,11 +706,13 @@ class FileNamespaceManager(OpenResourceNamespaceManager): namespace_classes = {} ContainerContext = dict - + + class ContainerMeta(type): def __init__(cls, classname, bases, dict_): namespace_classes[cls] = cls.namespace_class return type.__init__(cls, classname, bases, dict_) + def __call__(self, key, context, namespace, createfunc=None, expiretime=None, starttime=None, **kwargs): if namespace in context: @@ -617,16 +723,27 @@ class ContainerMeta(type): return Value(key, ns, createfunc=createfunc, expiretime=expiretime, starttime=starttime) + class Container(object): + """Implements synchronization and value-creation logic + for a 'value' stored in a :class:`.NamespaceManager`. + + :class:`.Container` and its subclasses are deprecated. The + :class:`.Value` class is now used for this purpose. + + """ __metaclass__ = ContainerMeta namespace_class = NamespaceManager + class FileContainer(Container): namespace_class = FileNamespaceManager + class MemoryContainer(Container): namespace_class = MemoryNamespaceManager + class DBMContainer(Container): namespace_class = DBMNamespaceManager diff --git a/module/lib/beaker/converters.py b/module/lib/beaker/converters.py index f0ad34963..3fb80692f 100644 --- a/module/lib/beaker/converters.py +++ b/module/lib/beaker/converters.py @@ -1,3 +1,5 @@ + + # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php def asbool(obj): @@ -12,6 +14,7 @@ def asbool(obj): "String is not true/false: %r" % obj) return bool(obj) + def aslist(obj, sep=None, strip=True): if isinstance(obj, (str, unicode)): lst = obj.split(sep) diff --git a/module/lib/beaker/crypto/__init__.py b/module/lib/beaker/crypto/__init__.py index 3e26b0c13..ac13da527 100644 --- a/module/lib/beaker/crypto/__init__.py +++ b/module/lib/beaker/crypto/__init__.py @@ -14,10 +14,14 @@ if util.jython: pass else: try: - from beaker.crypto.pycrypto import getKeyLength, aesEncrypt, aesDecrypt + from beaker.crypto.nsscrypto import getKeyLength, aesEncrypt, aesDecrypt keyLength = getKeyLength() except ImportError: - pass + try: + from beaker.crypto.pycrypto import getKeyLength, aesEncrypt, aesDecrypt + keyLength = getKeyLength() + except ImportError: + pass if not keyLength: has_aes = False diff --git a/module/lib/beaker/crypto/jcecrypto.py b/module/lib/beaker/crypto/jcecrypto.py index 4062d513e..ce313d6e1 100644 --- a/module/lib/beaker/crypto/jcecrypto.py +++ b/module/lib/beaker/crypto/jcecrypto.py @@ -16,6 +16,7 @@ import jarray # Initialization vector filled with zeros _iv = IvParameterSpec(jarray.zeros(16, 'b')) + def aesEncrypt(data, key): cipher = Cipher.getInstance('AES/CTR/NoPadding') skeySpec = SecretKeySpec(key, 'AES') @@ -25,6 +26,7 @@ def aesEncrypt(data, key): # magic. aesDecrypt = aesEncrypt + def getKeyLength(): maxlen = Cipher.getMaxAllowedKeyLength('AES/CTR/NoPadding') return min(maxlen, 256) / 8 diff --git a/module/lib/beaker/crypto/nsscrypto.py b/module/lib/beaker/crypto/nsscrypto.py new file mode 100644 index 000000000..3a7797877 --- /dev/null +++ b/module/lib/beaker/crypto/nsscrypto.py @@ -0,0 +1,45 @@ +"""Encryption module that uses nsscrypto""" +import nss.nss + +nss.nss.nss_init_nodb() + +# Apparently the rest of beaker doesn't care about the particluar cipher, +# mode and padding used. +# NOTE: A constant IV!!! This is only secure if the KEY is never reused!!! +_mech = nss.nss.CKM_AES_CBC_PAD +_iv = '\0' * nss.nss.get_iv_length(_mech) + +def aesEncrypt(data, key): + slot = nss.nss.get_best_slot(_mech) + + key_obj = nss.nss.import_sym_key(slot, _mech, nss.nss.PK11_OriginGenerated, + nss.nss.CKA_ENCRYPT, nss.nss.SecItem(key)) + + param = nss.nss.param_from_iv(_mech, nss.nss.SecItem(_iv)) + ctx = nss.nss.create_context_by_sym_key(_mech, nss.nss.CKA_ENCRYPT, key_obj, + param) + l1 = ctx.cipher_op(data) + # Yes, DIGEST. This needs fixing in NSS, but apparently nobody (including + # me :( ) cares enough. + l2 = ctx.digest_final() + + return l1 + l2 + +def aesDecrypt(data, key): + slot = nss.nss.get_best_slot(_mech) + + key_obj = nss.nss.import_sym_key(slot, _mech, nss.nss.PK11_OriginGenerated, + nss.nss.CKA_DECRYPT, nss.nss.SecItem(key)) + + param = nss.nss.param_from_iv(_mech, nss.nss.SecItem(_iv)) + ctx = nss.nss.create_context_by_sym_key(_mech, nss.nss.CKA_DECRYPT, key_obj, + param) + l1 = ctx.cipher_op(data) + # Yes, DIGEST. This needs fixing in NSS, but apparently nobody (including + # me :( ) cares enough. + l2 = ctx.digest_final() + + return l1 + l2 + +def getKeyLength(): + return 32 diff --git a/module/lib/beaker/crypto/pbkdf2.py b/module/lib/beaker/crypto/pbkdf2.py index 96dc5fbb2..71df22198 100644 --- a/module/lib/beaker/crypto/pbkdf2.py +++ b/module/lib/beaker/crypto/pbkdf2.py @@ -5,22 +5,22 @@ # # Copyright (C) 2007 Dwayne C. Litzenberger <dlitz@dlitz.net> # All rights reserved. -# +# # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies and that # both that copyright notice and this permission notice appear in # supporting documentation. -# -# THE AUTHOR PROVIDES THIS SOFTWARE ``AS IS'' AND ANY EXPRESSED OR -# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# +# THE AUTHOR PROVIDES THIS SOFTWARE ``AS IS'' AND ANY EXPRESSED OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Country of origin: Canada @@ -74,12 +74,14 @@ from base64 import b64encode from beaker.crypto.util import hmac as HMAC, hmac_sha1 as SHA1 + def strxor(a, b): return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)]) + class PBKDF2(object): """PBKDF2.py : PKCS#5 v2.0 Password-Based Key Derivation - + This implementation takes a passphrase and a salt (and optionally an iteration count, a digest module, and a MAC module) and provides a file-like object from which an arbitrarily-sized key can be read. @@ -89,10 +91,10 @@ class PBKDF2(object): The idea behind PBKDF2 is to derive a cryptographic key from a passphrase and a salt. - + PBKDF2 may also be used as a strong salted password hash. The 'crypt' function is provided for that purpose. - + Remember: Keys generated using PBKDF2 are only as strong as the passphrases they are derived from. """ @@ -109,7 +111,7 @@ class PBKDF2(object): """Pseudorandom function. e.g. HMAC-SHA1""" return self.__macmodule(key=key, msg=msg, digestmod=self.__digestmodule).digest() - + def read(self, bytes): """Read the specified number of key bytes.""" if self.closed: @@ -121,7 +123,7 @@ class PBKDF2(object): while size < bytes: i += 1 if i > 0xffffffff: - # We could return "" here, but + # We could return "" here, but raise OverflowError("derived key too long") block = self.__f(i) blocks.append(block) @@ -131,17 +133,17 @@ class PBKDF2(object): self.__buf = buf[bytes:] self.__blockNum = i return retval - + def __f(self, i): # i must fit within 32 bits - assert (1 <= i <= 0xffffffff) + assert (1 <= i and i <= 0xffffffff) U = self.__prf(self.__passphrase, self.__salt + pack("!L", i)) result = U - for j in xrange(2, 1+self.__iterations): + for j in xrange(2, 1 + self.__iterations): U = self.__prf(self.__passphrase, U) result = strxor(result, U) return result - + def hexread(self, octets): """Read the specified number of octets. Return them as hexadecimal. @@ -151,7 +153,7 @@ class PBKDF2(object): def _setup(self, passphrase, salt, iterations, prf): # Sanity checks: - + # passphrase and salt must be str or unicode (in the latter # case, we convert to UTF-8) if isinstance(passphrase, unicode): @@ -168,7 +170,7 @@ class PBKDF2(object): raise TypeError("iterations must be an integer") if iterations < 1: raise ValueError("iterations must be at least 1") - + # prf must be callable if not callable(prf): raise TypeError("prf must be callable") @@ -180,7 +182,7 @@ class PBKDF2(object): self.__blockNum = 0 self.__buf = "" self.closed = False - + def close(self): """Close the stream.""" if not self.closed: @@ -192,15 +194,16 @@ class PBKDF2(object): del self.__buf self.closed = True + def crypt(word, salt=None, iterations=None): """PBKDF2-based unix crypt(3) replacement. - + The number of iterations specified in the salt overrides the 'iterations' parameter. The effective hash length is 192 bits. """ - + # Generate a (pseudo-)random salt if the user hasn't provided one. if salt is None: salt = _makesalt() @@ -229,7 +232,7 @@ def crypt(word, salt=None, iterations=None): iterations = converted if not (iterations >= 1): raise ValueError("Invalid salt") - + # Make sure the salt matches the allowed character set allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./" for ch in salt: @@ -249,18 +252,20 @@ def crypt(word, salt=None, iterations=None): # crypt. PBKDF2.crypt = staticmethod(crypt) + def _makesalt(): """Return a 48-bit pseudorandom salt for crypt(). - + This function is not suitable for generating cryptographic secrets. """ binarysalt = "".join([pack("@H", randint(0, 0xffff)) for i in range(3)]) return b64encode(binarysalt, "./") + def test_pbkdf2(): """Module self-test""" from binascii import a2b_hex - + # # Test vectors from RFC 3962 # @@ -279,23 +284,23 @@ def test_pbkdf2(): raise RuntimeError("self-test failed") # Test 3 - result = PBKDF2("X"*64, "pass phrase equals block size", 1200).hexread(32) + result = PBKDF2("X" * 64, "pass phrase equals block size", 1200).hexread(32) expected = ("139c30c0966bc32ba55fdbf212530ac9" "c5ec59f1a452f5cc9ad940fea0598ed1") if result != expected: raise RuntimeError("self-test failed") - + # Test 4 - result = PBKDF2("X"*65, "pass phrase exceeds block size", 1200).hexread(32) + result = PBKDF2("X" * 65, "pass phrase exceeds block size", 1200).hexread(32) expected = ("9ccad6d468770cd51b10e6a68721be61" "1a8b4d282601db3b36be9246915ec82a") if result != expected: raise RuntimeError("self-test failed") - + # # Other test vectors # - + # Chunked read f = PBKDF2("kickstart", "workbench", 256) result = f.read(17) @@ -306,7 +311,7 @@ def test_pbkdf2(): expected = PBKDF2("kickstart", "workbench", 256).read(40) if result != expected: raise RuntimeError("self-test failed") - + # # crypt() test vectors # @@ -316,7 +321,7 @@ def test_pbkdf2(): expected = '$p5k2$$exec$r1EWMCMk7Rlv3L/RNcFXviDefYa0hlql' if result != expected: raise RuntimeError("self-test failed") - + # crypt 2 result = crypt("gnu", '$p5k2$c$u9HvcT4d$.....') expected = '$p5k2$c$u9HvcT4d$Sd1gwSVCLZYAuqZ25piRnbBEoAesaa/g' @@ -328,7 +333,7 @@ def test_pbkdf2(): expected = "$p5k2$d$tUsch7fU$nqDkaxMDOFBeJsTSfABsyn.PYUXilHwL" if result != expected: raise RuntimeError("self-test failed") - + # crypt 4 (unicode) result = crypt(u'\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2', '$p5k2$$KosHgqNo$9mjN8gqjt02hDoP0c2J0ABtLIwtot8cQ') diff --git a/module/lib/beaker/crypto/pycrypto.py b/module/lib/beaker/crypto/pycrypto.py index a3eb4d9db..6657bff56 100644 --- a/module/lib/beaker/crypto/pycrypto.py +++ b/module/lib/beaker/crypto/pycrypto.py @@ -9,23 +9,26 @@ try: def aesEncrypt(data, key): cipher = aes.AES(key) return cipher.process(data) - + # magic. aesDecrypt = aesEncrypt - + except ImportError: from Crypto.Cipher import AES + from Crypto.Util import Counter def aesEncrypt(data, key): - cipher = AES.new(key) - - data = data + (" " * (16 - (len(data) % 16))) + cipher = AES.new(key, AES.MODE_CTR, + counter=Counter.new(128, initial_value=0)) + return cipher.encrypt(data) def aesDecrypt(data, key): - cipher = AES.new(key) + cipher = AES.new(key, AES.MODE_CTR, + counter=Counter.new(128, initial_value=0)) + return cipher.decrypt(data) + - return cipher.decrypt(data).rstrip() def getKeyLength(): return 32 diff --git a/module/lib/beaker/crypto/util.py b/module/lib/beaker/crypto/util.py index d97e8ce6f..7f96ac856 100644 --- a/module/lib/beaker/crypto/util.py +++ b/module/lib/beaker/crypto/util.py @@ -6,9 +6,9 @@ try: # Use PyCrypto (if available) from Crypto.Hash import HMAC as hmac, SHA as hmac_sha1 sha1 = hmac_sha1.new - + except ImportError: - + # PyCrypto not available. Use the Python standard library. import hmac diff --git a/module/lib/beaker/exceptions.py b/module/lib/beaker/exceptions.py index cc0eed286..4f81e456d 100644 --- a/module/lib/beaker/exceptions.py +++ b/module/lib/beaker/exceptions.py @@ -1,9 +1,14 @@ """Beaker exception classes""" + class BeakerException(Exception): pass +class BeakerWarning(RuntimeWarning): + """Issued at runtime.""" + + class CreationAbortedError(Exception): """Deprecated.""" diff --git a/module/lib/beaker/ext/database.py b/module/lib/beaker/ext/database.py index 701e6f7d2..462fb8de4 100644 --- a/module/lib/beaker/ext/database.py +++ b/module/lib/beaker/ext/database.py @@ -14,6 +14,7 @@ sa = None pool = None types = None + class DatabaseNamespaceManager(OpenResourceNamespaceManager): metadatas = SyncDict() tables = SyncDict() @@ -30,12 +31,12 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): except ImportError: raise InvalidCacheBackendError("Database cache backend requires " "the 'sqlalchemy' library") - + def __init__(self, namespace, url=None, sa_opts=None, optimistic=False, table_name='beaker_cache', data_dir=None, lock_dir=None, - **params): + schema_name=None, **params): """Creates a database namespace manager - + ``url`` SQLAlchemy compliant db url ``sa_opts`` @@ -47,9 +48,11 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): numbers. ``table_name`` The table name to use in the database for the cache. + ``schema_name`` + The schema name to use in the database for the cache. """ OpenResourceNamespaceManager.__init__(self, namespace) - + if sa_opts is None: sa_opts = params @@ -58,14 +61,16 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): elif data_dir: self.lock_dir = data_dir + "/container_db_lock" if self.lock_dir: - verify_directory(self.lock_dir) - + verify_directory(self.lock_dir) + # Check to see if the table's been created before url = url or sa_opts['sa.url'] table_key = url + table_name + def make_cache(): # Check to see if we have a connection pool open already meta_key = url + table_name + def make_meta(): # SQLAlchemy pops the url, this ensures it sticks around # later @@ -82,7 +87,8 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): sa.Column('accessed', types.DateTime, nullable=False), sa.Column('created', types.DateTime, nullable=False), sa.Column('data', types.PickleType, nullable=False), - sa.UniqueConstraint('namespace') + sa.UniqueConstraint('namespace'), + schema=schema_name if schema_name else meta.schema ) cache.create(checkfirst=True) return cache @@ -90,24 +96,26 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): self._is_new = False self.loaded = False self.cache = DatabaseNamespaceManager.tables.get(table_key, make_cache) - + def get_access_lock(self): return null_synchronizer() def get_creation_lock(self, key): return file_synchronizer( - identifier ="databasecontainer/funclock/%s" % self.namespace, - lock_dir = self.lock_dir) + identifier="databasecontainer/funclock/%s/%s" % ( + self.namespace, key + ), + lock_dir=self.lock_dir) - def do_open(self, flags): + def do_open(self, flags, replace): # If we already loaded the data, don't bother loading it again if self.loaded: self.flags = flags return - + cache = self.cache - result = sa.select([cache.c.data], - cache.c.namespace==self.namespace + result = sa.select([cache.c.data], + cache.c.namespace == self.namespace ).execute().fetchone() if not result: self._is_new = True @@ -123,7 +131,7 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): self._is_new = True self.flags = flags self.loaded = True - + def do_close(self): if self.flags is not None and (self.flags == 'c' or self.flags == 'w'): cache = self.cache @@ -133,25 +141,25 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): created=datetime.now()) self._is_new = False else: - cache.update(cache.c.namespace==self.namespace).execute( + cache.update(cache.c.namespace == self.namespace).execute( data=self.hash, accessed=datetime.now()) self.flags = None - + def do_remove(self): cache = self.cache - cache.delete(cache.c.namespace==self.namespace).execute() + cache.delete(cache.c.namespace == self.namespace).execute() self.hash = {} - + # We can retain the fact that we did a load attempt, but since the # file is gone this will be a new namespace should it be saved. self._is_new = True - def __getitem__(self, key): + def __getitem__(self, key): return self.hash[key] - def __contains__(self, key): - return self.hash.has_key(key) - + def __contains__(self, key): + return key in self.hash + def __setitem__(self, key, value): self.hash[key] = value @@ -161,5 +169,6 @@ class DatabaseNamespaceManager(OpenResourceNamespaceManager): def keys(self): return self.hash.keys() + class DatabaseContainer(Container): namespace_manager = DatabaseNamespaceManager diff --git a/module/lib/beaker/ext/google.py b/module/lib/beaker/ext/google.py index dd8380d7f..d0a6205f4 100644 --- a/module/lib/beaker/ext/google.py +++ b/module/lib/beaker/ext/google.py @@ -10,6 +10,7 @@ log = logging.getLogger(__name__) db = None + class GoogleNamespaceManager(OpenResourceNamespaceManager): tables = {} @@ -23,11 +24,11 @@ class GoogleNamespaceManager(OpenResourceNamespaceManager): except ImportError: raise InvalidCacheBackendError("Datastore cache backend requires the " "'google.appengine.ext' library") - + def __init__(self, namespace, table_name='beaker_cache', **params): """Creates a datastore namespace manager""" OpenResourceNamespaceManager.__init__(self, namespace) - + def make_cache(): table_dict = dict(created=db.DateTimeProperty(), accessed=db.DateTimeProperty(), @@ -40,11 +41,11 @@ class GoogleNamespaceManager(OpenResourceNamespaceManager): self._is_new = False self.loaded = False self.log_debug = logging.DEBUG >= log.getEffectiveLevel() - + # Google wants namespaces to start with letters, change the namespace # to start with a letter self.namespace = 'p%s' % self.namespace - + def get_access_lock(self): return null_synchronizer() @@ -52,14 +53,14 @@ class GoogleNamespaceManager(OpenResourceNamespaceManager): # this is weird, should probably be present return null_synchronizer() - def do_open(self, flags): + def do_open(self, flags, replace): # If we already loaded the data, don't bother loading it again if self.loaded: self.flags = flags return - + item = self.cache.get_by_key_name(self.namespace) - + if not item: self._is_new = True self.hash = {} @@ -74,7 +75,7 @@ class GoogleNamespaceManager(OpenResourceNamespaceManager): self._is_new = True self.flags = flags self.loaded = True - + def do_close(self): if self.flags is not None and (self.flags == 'c' or self.flags == 'w'): if self._is_new: @@ -90,12 +91,12 @@ class GoogleNamespaceManager(OpenResourceNamespaceManager): item.accessed = datetime.now() item.put() self.flags = None - + def do_remove(self): item = self.cache.get_by_key_name(self.namespace) item.delete() self.hash = {} - + # We can retain the fact that we did a load attempt, but since the # file is gone this will be a new namespace should it be saved. self._is_new = True @@ -103,9 +104,9 @@ class GoogleNamespaceManager(OpenResourceNamespaceManager): def __getitem__(self, key): return self.hash[key] - def __contains__(self, key): - return self.hash.has_key(key) - + def __contains__(self, key): + return key in self.hash + def __setitem__(self, key, value): self.hash[key] = value @@ -114,7 +115,7 @@ class GoogleNamespaceManager(OpenResourceNamespaceManager): def keys(self): return self.hash.keys() - + class GoogleContainer(Container): namespace_class = GoogleNamespaceManager diff --git a/module/lib/beaker/ext/memcached.py b/module/lib/beaker/ext/memcached.py index 96516953f..94e3da3c9 100644 --- a/module/lib/beaker/ext/memcached.py +++ b/module/lib/beaker/ext/memcached.py @@ -1,54 +1,118 @@ +from __future__ import with_statement from beaker.container import NamespaceManager, Container +from beaker.crypto.util import sha1 from beaker.exceptions import InvalidCacheBackendError, MissingCacheParameter -from beaker.synchronization import file_synchronizer, null_synchronizer -from beaker.util import verify_directory, SyncDict +from beaker.synchronization import file_synchronizer +from beaker.util import verify_directory, SyncDict, parse_memcached_behaviors import warnings -memcache = None +MAX_KEY_LENGTH = 250 -class MemcachedNamespaceManager(NamespaceManager): - clients = SyncDict() - - @classmethod - def _init_dependencies(cls): +_client_libs = {} + + +def _load_client(name='auto'): + if name in _client_libs: + return _client_libs[name] + + def _pylibmc(): + global pylibmc + import pylibmc + return pylibmc + + def _cmemcache(): + global cmemcache + import cmemcache + warnings.warn("cmemcache is known to have serious " + "concurrency issues; consider using 'memcache' " + "or 'pylibmc'") + return cmemcache + + def _memcache(): global memcache - if memcache is not None: - return - try: - import pylibmc as memcache - except ImportError: + import memcache + return memcache + + def _auto(): + for _client in (_pylibmc, _cmemcache, _memcache): try: - import cmemcache as memcache - warnings.warn("cmemcache is known to have serious " - "concurrency issues; consider using 'memcache' or 'pylibmc'") + return _client() except ImportError: - try: - import memcache - except ImportError: - raise InvalidCacheBackendError("Memcached cache backend requires either " - "the 'memcache' or 'cmemcache' library") - - def __init__(self, namespace, url=None, data_dir=None, lock_dir=None, **params): + pass + else: + raise InvalidCacheBackendError( + "Memcached cache backend requires one " + "of: 'pylibmc' or 'memcache' to be installed.") + + clients = { + 'pylibmc': _pylibmc, + 'cmemcache': _cmemcache, + 'memcache': _memcache, + 'auto': _auto + } + _client_libs[name] = clib = clients[name]() + return clib + + +def _is_configured_for_pylibmc(memcache_module_config, memcache_client): + return memcache_module_config == 'pylibmc' or \ + memcache_client.__name__.startswith('pylibmc') + + +class MemcachedNamespaceManager(NamespaceManager): + """Provides the :class:`.NamespaceManager` API over a memcache client library.""" + + clients = SyncDict() + + def __new__(cls, *args, **kw): + memcache_module = kw.pop('memcache_module', 'auto') + + memcache_client = _load_client(memcache_module) + + if _is_configured_for_pylibmc(memcache_module, memcache_client): + return object.__new__(PyLibMCNamespaceManager) + else: + return object.__new__(MemcachedNamespaceManager) + + def __init__(self, namespace, url, + memcache_module='auto', + data_dir=None, lock_dir=None, + **kw): NamespaceManager.__init__(self, namespace) - + + _memcache_module = _client_libs[memcache_module] + if not url: - raise MissingCacheParameter("url is required") - + raise MissingCacheParameter("url is required") + if lock_dir: self.lock_dir = lock_dir elif data_dir: self.lock_dir = data_dir + "/container_mcd_lock" if self.lock_dir: - verify_directory(self.lock_dir) - - self.mc = MemcachedNamespaceManager.clients.get(url, memcache.Client, url.split(';')) + verify_directory(self.lock_dir) + + # Check for pylibmc namespace manager, in which case client will be + # instantiated by subclass __init__, to handle behavior passing to the + # pylibmc client + if not _is_configured_for_pylibmc(memcache_module, _memcache_module): + self.mc = MemcachedNamespaceManager.clients.get( + (memcache_module, url), + _memcache_module.Client, + url.split(';')) def get_creation_lock(self, key): return file_synchronizer( - identifier="memcachedcontainer/funclock/%s" % self.namespace,lock_dir = self.lock_dir) + identifier="memcachedcontainer/funclock/%s/%s" % + (self.namespace, key), lock_dir=self.lock_dir) def _format_key(self, key): - return self.namespace + '_' + key.replace(' ', '\302\267') + if not isinstance(key, str): + key = key.decode('ascii') + formated_key = (self.namespace + '_' + key).replace(' ', '\302\267') + if len(formated_key) > MAX_KEY_LENGTH: + formated_key = sha1(formated_key).hexdigest() + return formated_key def __getitem__(self, key): return self.mc.get(self._format_key(key)) @@ -68,15 +132,72 @@ class MemcachedNamespaceManager(NamespaceManager): def __setitem__(self, key, value): self.set_value(key, value) - + def __delitem__(self, key): self.mc.delete(self._format_key(key)) def do_remove(self): self.mc.flush_all() - + def keys(self): - raise NotImplementedError("Memcache caching does not support iteration of all cache keys") + raise NotImplementedError( + "Memcache caching does not " + "support iteration of all cache keys") + + +class PyLibMCNamespaceManager(MemcachedNamespaceManager): + """Provide thread-local support for pylibmc.""" + + def __init__(self, *arg, **kw): + super(PyLibMCNamespaceManager, self).__init__(*arg, **kw) + + memcache_module = kw.get('memcache_module', 'auto') + _memcache_module = _client_libs[memcache_module] + protocol = kw.get('protocol', 'text') + username = kw.get('username', None) + password = kw.get('password', None) + url = kw.get('url') + behaviors = parse_memcached_behaviors(kw) + + self.mc = MemcachedNamespaceManager.clients.get( + (memcache_module, url), + _memcache_module.Client, + servers=url.split(';'), behaviors=behaviors, + binary=(protocol == 'binary'), username=username, + password=password) + self.pool = pylibmc.ThreadMappedPool(self.mc) + + def __getitem__(self, key): + with self.pool.reserve() as mc: + return mc.get(self._format_key(key)) + + def __contains__(self, key): + with self.pool.reserve() as mc: + value = mc.get(self._format_key(key)) + return value is not None + + def has_key(self, key): + return key in self + + def set_value(self, key, value, expiretime=None): + with self.pool.reserve() as mc: + if expiretime: + mc.set(self._format_key(key), value, time=expiretime) + else: + mc.set(self._format_key(key), value) + + def __setitem__(self, key, value): + self.set_value(key, value) + + def __delitem__(self, key): + with self.pool.reserve() as mc: + mc.delete(self._format_key(key)) + + def do_remove(self): + with self.pool.reserve() as mc: + mc.flush_all() + class MemcachedContainer(Container): + """Container class which invokes :class:`.MemcacheNamespaceManager`.""" namespace_class = MemcachedNamespaceManager diff --git a/module/lib/beaker/ext/sqla.py b/module/lib/beaker/ext/sqla.py index 8c79633c1..6405c2919 100644 --- a/module/lib/beaker/ext/sqla.py +++ b/module/lib/beaker/ext/sqla.py @@ -13,6 +13,7 @@ log = logging.getLogger(__name__) sa = None + class SqlaNamespaceManager(OpenResourceNamespaceManager): binds = SyncDict() tables = SyncDict() @@ -47,7 +48,7 @@ class SqlaNamespaceManager(OpenResourceNamespaceManager): elif data_dir: self.lock_dir = data_dir + "/container_db_lock" if self.lock_dir: - verify_directory(self.lock_dir) + verify_directory(self.lock_dir) self.bind = self.__class__.binds.get(str(bind.url), lambda: bind) self.table = self.__class__.tables.get('%s:%s' % (bind.url, table.name), @@ -61,10 +62,10 @@ class SqlaNamespaceManager(OpenResourceNamespaceManager): def get_creation_lock(self, key): return file_synchronizer( - identifier ="databasecontainer/funclock/%s" % self.namespace, + identifier="databasecontainer/funclock/%s" % self.namespace, lock_dir=self.lock_dir) - def do_open(self, flags): + def do_open(self, flags, replace): if self.loaded: self.flags = flags return @@ -108,7 +109,7 @@ class SqlaNamespaceManager(OpenResourceNamespaceManager): return self.hash[key] def __contains__(self, key): - return self.hash.has_key(key) + return key in self.hash def __setitem__(self, key, value): self.hash[key] = value @@ -123,11 +124,13 @@ class SqlaNamespaceManager(OpenResourceNamespaceManager): class SqlaContainer(Container): namespace_manager = SqlaNamespaceManager -def make_cache_table(metadata, table_name='beaker_cache'): + +def make_cache_table(metadata, table_name='beaker_cache', schema_name=None): """Return a ``Table`` object suitable for storing cached values for the namespace manager. Do not create the table.""" return sa.Table(table_name, metadata, sa.Column('namespace', sa.String(255), primary_key=True), sa.Column('accessed', sa.DateTime, nullable=False), sa.Column('created', sa.DateTime, nullable=False), - sa.Column('data', sa.PickleType, nullable=False)) + sa.Column('data', sa.PickleType, nullable=False), + schema=schema_name if schema_name else metadata.schema) diff --git a/module/lib/beaker/middleware.py b/module/lib/beaker/middleware.py index 7ba88b37d..803398584 100644 --- a/module/lib/beaker/middleware.py +++ b/module/lib/beaker/middleware.py @@ -16,15 +16,15 @@ from beaker.util import coerce_cache_params, coerce_session_params, \ class CacheMiddleware(object): cache = beaker_cache - + def __init__(self, app, config=None, environ_key='beaker.cache', **kwargs): """Initialize the Cache Middleware - - The Cache middleware will make a Cache instance available + + The Cache middleware will make a CacheManager instance available every request under the ``environ['beaker.cache']`` key by default. The location in environ can be changed by setting ``environ_key``. - + ``config`` dict All settings should be prefixed by 'cache.'. This method of passing variables is intended for Paste and other @@ -32,11 +32,11 @@ class CacheMiddleware(object): single dictionary. If config contains *no cache. prefixed args*, then *all* of the config options will be used to intialize the Cache objects. - + ``environ_key`` Location where the Cache instance will keyed in the WSGI environ - + ``**kwargs`` All keyword arguments are assumed to be cache settings and will override any settings found in ``config`` @@ -44,26 +44,26 @@ class CacheMiddleware(object): """ self.app = app config = config or {} - + self.options = {} - + # Update the options with the parsed config self.options.update(parse_cache_config_options(config)) - + # Add any options from kwargs, but leave out the defaults this # time self.options.update( parse_cache_config_options(kwargs, include_defaults=False)) - + # Assume all keys are intended for cache if none are prefixed with # 'cache.' if not self.options and config: self.options = config - + self.options.update(kwargs) self.cache_manager = CacheManager(**self.options) self.environ_key = environ_key - + def __call__(self, environ, start_response): if environ.get('paste.registry'): if environ['paste.registry'].reglist: @@ -75,16 +75,16 @@ class CacheMiddleware(object): class SessionMiddleware(object): session = beaker_session - + def __init__(self, wrap_app, config=None, environ_key='beaker.session', **kwargs): """Initialize the Session Middleware - + The Session middleware will make a lazy session instance available every request under the ``environ['beaker.session']`` key by default. The location in environ can be changed by setting ``environ_key``. - + ``config`` dict All settings should be prefixed by 'session.'. This method of passing variables is intended for Paste and other @@ -92,21 +92,21 @@ class SessionMiddleware(object): single dictionary. If config contains *no cache. prefixed args*, then *all* of the config options will be used to intialize the Cache objects. - + ``environ_key`` Location where the Session instance will keyed in the WSGI environ - + ``**kwargs`` All keyword arguments are assumed to be session settings and will override any settings found in ``config`` """ config = config or {} - + # Load up the default params - self.options = dict(invalidate_corrupt=True, type=None, - data_dir=None, key='beaker.session.id', + self.options = dict(invalidate_corrupt=True, type=None, + data_dir=None, key='beaker.session.id', timeout=None, secret=None, log_file=None) # Pull out any config args meant for beaker session. if there are any @@ -120,19 +120,19 @@ class SessionMiddleware(object): warnings.warn('Session options should start with session. ' 'instead of session_.', DeprecationWarning, 2) self.options[key[8:]] = val - + # Coerce and validate session params coerce_session_params(self.options) - + # Assume all keys are intended for cache if none are prefixed with # 'cache.' if not self.options and config: self.options = config - + self.options.update(kwargs) - self.wrap_app = wrap_app + self.wrap_app = self.app = wrap_app self.environ_key = environ_key - + def __call__(self, environ, start_response): session = SessionObject(environ, **self.options) if environ.get('paste.registry'): @@ -140,8 +140,11 @@ class SessionMiddleware(object): environ['paste.registry'].register(self.session, session) environ[self.environ_key] = session environ['beaker.get_session'] = self._get_session - - def session_start_response(status, headers, exc_info = None): + + if 'paste.testing_variables' in environ and 'webtest_varname' in self.options: + environ['paste.testing_variables'][self.options['webtest_varname']] = session + + def session_start_response(status, headers, exc_info=None): if session.accessed(): session.persist() if session.__dict__['_headers']['set_cookie']: @@ -150,7 +153,7 @@ class SessionMiddleware(object): headers.append(('Set-cookie', cookie)) return start_response(status, headers, exc_info) return self.wrap_app(environ, session_start_response) - + def _get_session(self): return Session({}, use_cookies=False, **self.options) diff --git a/module/lib/beaker/session.py b/module/lib/beaker/session.py index 7d465530b..d70a670eb 100644 --- a/module/lib/beaker/session.py +++ b/module/lib/beaker/session.py @@ -1,13 +1,9 @@ import Cookie import os -import random -import time from datetime import datetime, timedelta - +import time from beaker.crypto import hmac as HMAC, hmac_sha1 as SHA1, md5 -from beaker.util import pickle - -from beaker import crypto +from beaker import crypto, util from beaker.cache import clsmap from beaker.exceptions import BeakerException, InvalidCryptoBackendError from base64 import b64encode, b64decode @@ -15,56 +11,102 @@ from base64 import b64encode, b64decode __all__ = ['SignedCookie', 'Session'] -getpid = hasattr(os, 'getpid') and os.getpid or (lambda : '') + +try: + import uuid + + def _session_id(): + return uuid.uuid4().hex +except ImportError: + import random + if hasattr(os, 'getpid'): + getpid = os.getpid + else: + def getpid(): + return '' + + def _session_id(): + id_str = "%f%s%f%s" % ( + time.time(), + id({}), + random.random(), + getpid() + ) + if util.py3k: + return md5( + md5( + id_str.encode('ascii') + ).hexdigest().encode('ascii') + ).hexdigest() + else: + return md5(md5(id_str).hexdigest()).hexdigest() + class SignedCookie(Cookie.BaseCookie): """Extends python cookie to give digital signature support""" def __init__(self, secret, input=None): - self.secret = secret + self.secret = secret.encode('UTF-8') Cookie.BaseCookie.__init__(self, input) - + def value_decode(self, val): val = val.strip('"') - sig = HMAC.new(self.secret, val[40:], SHA1).hexdigest() - + sig = HMAC.new(self.secret, val[40:].encode('UTF-8'), SHA1).hexdigest() + # Avoid timing attacks invalid_bits = 0 input_sig = val[:40] if len(sig) != len(input_sig): return None, val - + for a, b in zip(sig, input_sig): invalid_bits += a != b - + if invalid_bits: return None, val else: return val[40:], val - + def value_encode(self, val): - sig = HMAC.new(self.secret, val, SHA1).hexdigest() + sig = HMAC.new(self.secret, val.encode('UTF-8'), SHA1).hexdigest() return str(val), ("%s%s" % (sig, val)) class Session(dict): """Session object that uses container package for storage. - - ``key`` - The name the cookie should be set to. - ``timeout`` - How long session data is considered valid. This is used - regardless of the cookie being present or not to determine - whether session data is still valid. - ``cookie_domain`` - Domain to use for the cookie. - ``secure`` - Whether or not the cookie should only be sent over SSL. + + :param invalidate_corrupt: How to handle corrupt data when loading. When + set to True, then corrupt data will be silently + invalidated and a new session created, + otherwise invalid data will cause an exception. + :type invalidate_corrupt: bool + :param use_cookies: Whether or not cookies should be created. When set to + False, it is assumed the user will handle storing the + session on their own. + :type use_cookies: bool + :param type: What data backend type should be used to store the underlying + session data + :param key: The name the cookie should be set to. + :param timeout: How long session data is considered valid. This is used + regardless of the cookie being present or not to determine + whether session data is still valid. + :type timeout: int + :param cookie_expires: Expiration date for cookie + :param cookie_domain: Domain to use for the cookie. + :param cookie_path: Path to use for the cookie. + :param secure: Whether or not the cookie should only be sent over SSL. + :param httponly: Whether or not the cookie should only be accessible by + the browser not by JavaScript. + :param encrypt_key: The key to use for the local session encryption, if not + provided the session will not be encrypted. + :param validate_key: The key used to sign the local encrypted session + """ def __init__(self, request, id=None, invalidate_corrupt=False, use_cookies=True, type=None, data_dir=None, key='beaker.session.id', timeout=None, cookie_expires=True, - cookie_domain=None, secret=None, secure=False, - namespace_class=None, **namespace_args): + cookie_domain=None, cookie_path='/', secret=None, + secure=False, namespace_class=None, httponly=False, + encrypt_key=None, validate_key=None, **namespace_args): if not type: if data_dir: self.type = 'file' @@ -76,24 +118,28 @@ class Session(dict): self.namespace_class = namespace_class or clsmap[self.type] self.namespace_args = namespace_args - + self.request = request self.data_dir = data_dir self.key = key - + self.timeout = timeout self.use_cookies = use_cookies self.cookie_expires = cookie_expires - + # Default cookie domain/path self._domain = cookie_domain - self._path = '/' + self._path = cookie_path self.was_invalidated = False self.secret = secret self.secure = secure + self.httponly = httponly + self.encrypt_key = encrypt_key + self.validate_key = validate_key self.id = id self.accessed_dict = {} - + self.invalidate_corrupt = invalidate_corrupt + if self.use_cookies: cookieheader = request.get('cookie', '') if secret: @@ -103,10 +149,10 @@ class Session(dict): self.cookie = SignedCookie(secret, input=None) else: self.cookie = Cookie.SimpleCookie(input=cookieheader) - + if not self.id and self.key in self.cookie: self.id = self.cookie[self.key].value - + self.is_new = self.id is None if self.is_new: self._create_id() @@ -114,80 +160,146 @@ class Session(dict): else: try: self.load() - except: + except Exception, e: if invalidate_corrupt: + util.warn( + "Invalidating corrupt session %s; " + "error was: %s. Set invalidate_corrupt=False " + "to propagate this exception." % (self.id, e)) self.invalidate() else: raise - - def _create_id(self): - self.id = md5( - md5("%f%s%f%s" % (time.time(), id({}), random.random(), - getpid())).hexdigest(), - ).hexdigest() - self.is_new = True - self.last_accessed = None - if self.use_cookies: - self.cookie[self.key] = self.id - if self._domain: - self.cookie[self.key]['domain'] = self._domain - if self.secure: - self.cookie[self.key]['secure'] = True - self.cookie[self.key]['path'] = self._path + + def has_key(self, name): + return name in self + + def _set_cookie_values(self, expires=None): + self.cookie[self.key] = self.id + if self._domain: + self.cookie[self.key]['domain'] = self._domain + if self.secure: + self.cookie[self.key]['secure'] = True + self._set_cookie_http_only() + self.cookie[self.key]['path'] = self._path + + self._set_cookie_expires(expires) + + def _set_cookie_expires(self, expires): + if expires is None: if self.cookie_expires is not True: if self.cookie_expires is False: - expires = datetime.fromtimestamp( 0x7FFFFFFF ) + expires = datetime.fromtimestamp(0x7FFFFFFF) elif isinstance(self.cookie_expires, timedelta): - expires = datetime.today() + self.cookie_expires + expires = datetime.utcnow() + self.cookie_expires elif isinstance(self.cookie_expires, datetime): expires = self.cookie_expires else: raise ValueError("Invalid argument for cookie_expires: %s" % repr(self.cookie_expires)) - self.cookie[self.key]['expires'] = \ - expires.strftime("%a, %d-%b-%Y %H:%M:%S GMT" ) - self.request['cookie_out'] = self.cookie[self.key].output(header='') - self.request['set_cookie'] = False - + else: + expires = None + if expires is not None: + if not self.cookie or self.key not in self.cookie: + self.cookie[self.key] = self.id + self.cookie[self.key]['expires'] = \ + expires.strftime("%a, %d-%b-%Y %H:%M:%S GMT") + return expires + + def _update_cookie_out(self, set_cookie=True): + self.request['cookie_out'] = self.cookie[self.key].output(header='') + self.request['set_cookie'] = set_cookie + + def _set_cookie_http_only(self): + try: + if self.httponly: + self.cookie[self.key]['httponly'] = True + except Cookie.CookieError, e: + if 'Invalid Attribute httponly' not in str(e): + raise + util.warn('Python 2.6+ is required to use httponly') + + def _create_id(self, set_new=True): + self.id = _session_id() + + if set_new: + self.is_new = True + self.last_accessed = None + if self.use_cookies: + self._set_cookie_values() + sc = set_new == False + self._update_cookie_out(set_cookie=sc) + + @property def created(self): return self['_creation_time'] - created = property(created) - + def _set_domain(self, domain): self['_domain'] = domain self.cookie[self.key]['domain'] = domain - self.request['cookie_out'] = self.cookie[self.key].output(header='') - self.request['set_cookie'] = True - + self._update_cookie_out() + def _get_domain(self): return self._domain - + domain = property(_get_domain, _set_domain) - + def _set_path(self, path): - self['_path'] = path + self['_path'] = self._path = path self.cookie[self.key]['path'] = path - self.request['cookie_out'] = self.cookie[self.key].output(header='') - self.request['set_cookie'] = True - + self._update_cookie_out() + def _get_path(self): return self._path - + path = property(_get_path, _set_path) + def _encrypt_data(self, session_data=None): + """Serialize, encipher, and base64 the session dict""" + session_data = session_data or self.copy() + if self.encrypt_key: + nonce = b64encode(os.urandom(6))[:8] + encrypt_key = crypto.generateCryptoKeys(self.encrypt_key, + self.validate_key + nonce, 1) + data = util.pickle.dumps(session_data, 2) + return nonce + b64encode(crypto.aesEncrypt(data, encrypt_key)) + else: + data = util.pickle.dumps(session_data, 2) + return b64encode(data) + + def _decrypt_data(self, session_data): + """Bas64, decipher, then un-serialize the data for the session + dict""" + if self.encrypt_key: + try: + nonce = session_data[:8] + encrypt_key = crypto.generateCryptoKeys(self.encrypt_key, + self.validate_key + nonce, 1) + payload = b64decode(session_data[8:]) + data = crypto.aesDecrypt(payload, encrypt_key) + except: + # As much as I hate a bare except, we get some insane errors + # here that get tossed when crypto fails, so we raise the + # 'right' exception + if self.invalidate_corrupt: + return None + else: + raise + try: + return util.pickle.loads(data) + except: + if self.invalidate_corrupt: + return None + else: + raise + else: + data = b64decode(session_data) + return util.pickle.loads(data) + def _delete_cookie(self): self.request['set_cookie'] = True - self.cookie[self.key] = self.id - if self._domain: - self.cookie[self.key]['domain'] = self._domain - if self.secure: - self.cookie[self.key]['secure'] = True - self.cookie[self.key]['path'] = '/' - expires = datetime.today().replace(year=2003) - self.cookie[self.key]['expires'] = \ - expires.strftime("%a, %d-%b-%Y %H:%M:%S GMT" ) - self.request['cookie_out'] = self.cookie[self.key].output(header='') - self.request['set_cookie'] = True + expires = datetime.utcnow() - timedelta(365) + self._set_cookie_values(expires) + self._update_cookie_out() def delete(self): """Deletes the session from the persistent storage, and sends @@ -203,15 +315,17 @@ class Session(dict): self.was_invalidated = True self._create_id() self.load() - + def load(self): "Loads the data from this session from persistent storage" self.namespace = self.namespace_class(self.id, - data_dir=self.data_dir, digest_filenames=False, + data_dir=self.data_dir, + digest_filenames=False, **self.namespace_args) now = time.time() - self.request['set_cookie'] = True - + if self.use_cookies: + self.request['set_cookie'] = True + self.namespace.acquire_read_lock() timed_out = False try: @@ -219,24 +333,34 @@ class Session(dict): try: session_data = self.namespace['session'] + if (session_data is not None and self.encrypt_key): + session_data = self._decrypt_data(session_data) + # Memcached always returns a key, its None when its not # present if session_data is None: session_data = { - '_creation_time':now, - '_accessed_time':now + '_creation_time': now, + '_accessed_time': now } self.is_new = True except (KeyError, TypeError): session_data = { - '_creation_time':now, - '_accessed_time':now + '_creation_time': now, + '_accessed_time': now + } + self.is_new = True + + if session_data is None or len(session_data) == 0: + session_data = { + '_creation_time': now, + '_accessed_time': now } self.is_new = True - + if self.timeout is not None and \ now - session_data['_accessed_time'] > self.timeout: - timed_out= True + timed_out = True else: # Properly set the last_accessed time, which is different # than the *currently* _accessed_time @@ -244,43 +368,52 @@ class Session(dict): self.last_accessed = None else: self.last_accessed = session_data['_accessed_time'] - + # Update the current _accessed_time session_data['_accessed_time'] = now + + # Set the path if applicable + if '_path' in session_data: + self._path = session_data['_path'] self.update(session_data) - self.accessed_dict = session_data.copy() + self.accessed_dict = session_data.copy() finally: self.namespace.release_read_lock() if timed_out: self.invalidate() - + def save(self, accessed_only=False): """Saves the data for this session to persistent storage - + If accessed_only is True, then only the original data loaded at the beginning of the request will be saved, with the updated last accessed time. - + """ # Look to see if its a new session that was only accessed # Don't save it under that case if accessed_only and self.is_new: return None - - if not hasattr(self, 'namespace'): + + # this session might not have a namespace yet or the session id + # might have been regenerated + if not hasattr(self, 'namespace') or self.namespace.namespace != self.id: self.namespace = self.namespace_class( - self.id, + self.id, data_dir=self.data_dir, - digest_filenames=False, + digest_filenames=False, **self.namespace_args) - - self.namespace.acquire_write_lock() + + self.namespace.acquire_write_lock(replace=True) try: if accessed_only: data = dict(self.accessed_dict.items()) else: data = dict(self.items()) - + + if self.encrypt_key: + data = self._encrypt_data(data) + # Save the data if not data and 'session' in self.namespace: del self.namespace['session'] @@ -288,22 +421,32 @@ class Session(dict): self.namespace['session'] = data finally: self.namespace.release_write_lock() - if self.is_new: + if self.use_cookies and self.is_new: self.request['set_cookie'] = True - + def revert(self): """Revert the session to its original state from its first access in the request""" self.clear() self.update(self.accessed_dict) - + + def regenerate_id(self): + """ + creates a new session id, retains all session data + + Its a good security practice to regnerate the id after a client + elevates priviliges. + + """ + self._create_id(set_new=False) + # TODO: I think both these methods should be removed. They're from # the original mod_python code i was ripping off but they really # have no use here. def lock(self): """Locks this session against other processes/threads. This is automatic when load/save is called. - + ***use with caution*** and always with a corresponding 'unlock' inside a "finally:" block, as a stray lock typically cannot be unlocked without shutting down the whole application. @@ -322,37 +465,38 @@ class Session(dict): """ self.namespace.release_write_lock() + class CookieSession(Session): """Pure cookie-based session - + Options recognized when using cookie-based sessions are slightly more restricted than general sessions. - - ``key`` - The name the cookie should be set to. - ``timeout`` - How long session data is considered valid. This is used - regardless of the cookie being present or not to determine - whether session data is still valid. - ``encrypt_key`` - The key to use for the session encryption, if not provided the - session will not be encrypted. - ``validate_key`` - The key used to sign the encrypted session - ``cookie_domain`` - Domain to use for the cookie. - ``secure`` - Whether or not the cookie should only be sent over SSL. - + + :param key: The name the cookie should be set to. + :param timeout: How long session data is considered valid. This is used + regardless of the cookie being present or not to determine + whether session data is still valid. + :type timeout: int + :param cookie_expires: Expiration date for cookie + :param cookie_domain: Domain to use for the cookie. + :param cookie_path: Path to use for the cookie. + :param secure: Whether or not the cookie should only be sent over SSL. + :param httponly: Whether or not the cookie should only be accessible by + the browser not by JavaScript. + :param encrypt_key: The key to use for the local session encryption, if not + provided the session will not be encrypted. + :param validate_key: The key used to sign the local encrypted session + """ def __init__(self, request, key='beaker.session.id', timeout=None, - cookie_expires=True, cookie_domain=None, encrypt_key=None, - validate_key=None, secure=False, **kwargs): - + cookie_expires=True, cookie_domain=None, cookie_path='/', + encrypt_key=None, validate_key=None, secure=False, + httponly=False, **kwargs): + if not crypto.has_aes and encrypt_key: raise InvalidCryptoBackendError("No AES library is installed, can't generate " "encrypted cookie-only Session.") - + self.request = request self.key = key self.timeout = timeout @@ -361,31 +505,34 @@ class CookieSession(Session): self.validate_key = validate_key self.request['set_cookie'] = False self.secure = secure + self.httponly = httponly self._domain = cookie_domain - self._path = '/' - + self._path = cookie_path + try: cookieheader = request['cookie'] except KeyError: cookieheader = '' - + if validate_key is None: raise BeakerException("No validate_key specified for Cookie only " "Session.") - + try: self.cookie = SignedCookie(validate_key, input=cookieheader) except Cookie.CookieError: self.cookie = SignedCookie(validate_key, input=None) - - self['_id'] = self._make_id() + + self['_id'] = _session_id() self.is_new = True - + # If we have a cookie, load it if self.key in self.cookie and self.cookie[self.key].value is not None: self.is_new = False try: - self.update(self._decrypt_data()) + cookie_data = self.cookie[self.key].value + self.update(self._decrypt_data(cookie_data)) + self._path = self.get('_path', '/') except: pass if self.timeout is not None and time.time() - \ @@ -393,11 +540,11 @@ class CookieSession(Session): self.clear() self.accessed_dict = self.copy() self._create_cookie() - + def created(self): return self['_creation_time'] created = property(created) - + def id(self): return self['_id'] id = property(id) @@ -405,53 +552,20 @@ class CookieSession(Session): def _set_domain(self, domain): self['_domain'] = domain self._domain = domain - + def _get_domain(self): return self._domain - + domain = property(_get_domain, _set_domain) - + def _set_path(self, path): - self['_path'] = path - self._path = path - + self['_path'] = self._path = path + def _get_path(self): return self._path - + path = property(_get_path, _set_path) - def _encrypt_data(self): - """Serialize, encipher, and base64 the session dict""" - if self.encrypt_key: - nonce = b64encode(os.urandom(40))[:8] - encrypt_key = crypto.generateCryptoKeys(self.encrypt_key, - self.validate_key + nonce, 1) - data = pickle.dumps(self.copy(), 2) - return nonce + b64encode(crypto.aesEncrypt(data, encrypt_key)) - else: - data = pickle.dumps(self.copy(), 2) - return b64encode(data) - - def _decrypt_data(self): - """Bas64, decipher, then un-serialize the data for the session - dict""" - if self.encrypt_key: - nonce = self.cookie[self.key].value[:8] - encrypt_key = crypto.generateCryptoKeys(self.encrypt_key, - self.validate_key + nonce, 1) - payload = b64decode(self.cookie[self.key].value[8:]) - data = crypto.aesDecrypt(payload, encrypt_key) - return pickle.loads(data) - else: - data = b64decode(self.cookie[self.key].value) - return pickle.loads(data) - - def _make_id(self): - return md5(md5( - "%f%s%f%s" % (time.time(), id({}), random.random(), getpid()) - ).hexdigest() - ).hexdigest() - def save(self, accessed_only=False): """Saves the data for this session to persistent storage""" if accessed_only and self.is_new: @@ -460,88 +574,79 @@ class CookieSession(Session): self.clear() self.update(self.accessed_dict) self._create_cookie() - + def expire(self): """Delete the 'expires' attribute on this Session, if any.""" - + self.pop('_expires', None) - + def _create_cookie(self): if '_creation_time' not in self: self['_creation_time'] = time.time() if '_id' not in self: - self['_id'] = self._make_id() + self['_id'] = _session_id() self['_accessed_time'] = time.time() - - if self.cookie_expires is not True: - if self.cookie_expires is False: - expires = datetime.fromtimestamp( 0x7FFFFFFF ) - elif isinstance(self.cookie_expires, timedelta): - expires = datetime.today() + self.cookie_expires - elif isinstance(self.cookie_expires, datetime): - expires = self.cookie_expires - else: - raise ValueError("Invalid argument for cookie_expires: %s" - % repr(self.cookie_expires)) - self['_expires'] = expires - elif '_expires' in self: - expires = self['_expires'] - else: - expires = None val = self._encrypt_data() if len(val) > 4064: raise BeakerException("Cookie value is too long to store") - + self.cookie[self.key] = val + + if '_expires' in self: + expires = self['_expires'] + else: + expires = None + expires = self._set_cookie_expires(expires) + if expires is not None: + self['_expires'] = expires + if '_domain' in self: self.cookie[self.key]['domain'] = self['_domain'] elif self._domain: self.cookie[self.key]['domain'] = self._domain if self.secure: self.cookie[self.key]['secure'] = True - + self._set_cookie_http_only() + self.cookie[self.key]['path'] = self.get('_path', '/') - - if expires: - self.cookie[self.key]['expires'] = \ - expires.strftime("%a, %d-%b-%Y %H:%M:%S GMT" ) + self.request['cookie_out'] = self.cookie[self.key].output(header='') self.request['set_cookie'] = True - + def delete(self): """Delete the cookie, and clear the session""" # Send a delete cookie request self._delete_cookie() self.clear() - + def invalidate(self): """Clear the contents and start a new session""" - self.delete() - self['_id'] = self._make_id() + self.clear() + self['_id'] = _session_id() class SessionObject(object): """Session proxy/lazy creator - + This object proxies access to the actual session object, so that in the case that the session hasn't been used before, it will be setup. This avoid creating and loading the session from persistent storage unless its actually used during the request. - + """ def __init__(self, environ, **params): self.__dict__['_params'] = params self.__dict__['_environ'] = environ self.__dict__['_sess'] = None - self.__dict__['_headers'] = [] - + self.__dict__['_headers'] = {} + def _session(self): """Lazy initial creation of session object""" if self.__dict__['_sess'] is None: params = self.__dict__['_params'] environ = self.__dict__['_environ'] - self.__dict__['_headers'] = req = {'cookie_out':None} + self.__dict__['_headers'] = req = {'cookie_out': None} req['cookie'] = environ.get('HTTP_COOKIE') if params.get('type') == 'cookie': self.__dict__['_sess'] = CookieSession(req, **params) @@ -549,35 +654,38 @@ class SessionObject(object): self.__dict__['_sess'] = Session(req, use_cookies=True, **params) return self.__dict__['_sess'] - + def __getattr__(self, attr): return getattr(self._session(), attr) - + def __setattr__(self, attr, value): setattr(self._session(), attr, value) - + def __delattr__(self, name): self._session().__delattr__(name) - + def __getitem__(self, key): return self._session()[key] - + def __setitem__(self, key, value): self._session()[key] = value - + def __delitem__(self, key): self._session().__delitem__(key) - + def __repr__(self): return self._session().__repr__() - + def __iter__(self): """Only works for proxying to a dict""" return iter(self._session().keys()) - + def __contains__(self, key): - return self._session().has_key(key) - + return key in self._session() + + def has_key(self, key): + return key in self._session() + def get_by_id(self, id): """Loads a session given a session ID""" params = self.__dict__['_params'] @@ -585,22 +693,22 @@ class SessionObject(object): if session.is_new: return None return session - + def save(self): self.__dict__['_dirty'] = True - + def delete(self): self.__dict__['_dirty'] = True self._session().delete() - + def persist(self): """Persist the session to the storage - + If its set to autosave, then the entire session will be saved regardless of if save() has been called. Otherwise, just the accessed time will be updated if save() was not called, or the session will be saved if save() was called. - + """ if self.__dict__['_params'].get('auto'): self._session().save() @@ -609,10 +717,10 @@ class SessionObject(object): self._session().save() else: self._session().save(accessed_only=True) - + def dirty(self): return self.__dict__.get('_dirty', False) - + def accessed(self): """Returns whether or not the session has been accessed""" return self.__dict__['_sess'] is not None diff --git a/module/lib/beaker/synchronization.py b/module/lib/beaker/synchronization.py index 761303707..f236b8cfe 100644 --- a/module/lib/beaker/synchronization.py +++ b/module/lib/beaker/synchronization.py @@ -29,18 +29,18 @@ except: from beaker import util from beaker.exceptions import LockError -__all__ = ["file_synchronizer", "mutex_synchronizer", "null_synchronizer", +__all__ = ["file_synchronizer", "mutex_synchronizer", "null_synchronizer", "NameLock", "_threading"] class NameLock(object): """a proxy for an RLock object that is stored in a name based - registry. - + registry. + Multiple threads can get a reference to the same RLock based on the name alone, and synchronize operations related to that name. - """ + """ locks = util.WeakValuedRegistry() class NLContainer(object): @@ -49,17 +49,18 @@ class NameLock(object): self.lock = _threading.RLock() else: self.lock = _threading.Lock() + def __call__(self): return self.lock - def __init__(self, identifier = None, reentrant = False): + def __init__(self, identifier=None, reentrant=False): if identifier is None: self._lock = NameLock.NLContainer(reentrant) else: self._lock = NameLock.locks.get(identifier, NameLock.NLContainer, reentrant) - def acquire(self, wait = True): + def acquire(self, wait=True): return self._lock().acquire(wait) def release(self): @@ -67,6 +68,8 @@ class NameLock(object): _synchronizers = util.WeakValuedRegistry() + + def _synchronizer(identifier, cls, **kwargs): return _synchronizers.sync_get((identifier, cls), cls, identifier, **kwargs) @@ -83,12 +86,19 @@ def mutex_synchronizer(identifier, **kwargs): class null_synchronizer(object): + """A 'null' synchronizer, which provides the :class:`.SynchronizerImpl` interface + without any locking. + + """ def acquire_write_lock(self, wait=True): return True + def acquire_read_lock(self): pass + def release_write_lock(self): pass + def release_read_lock(self): pass acquire = acquire_write_lock @@ -96,6 +106,10 @@ class null_synchronizer(object): class SynchronizerImpl(object): + """Base class for a synchronization object that allows + multiple readers, single writers. + + """ def __init__(self): self._state = util.ThreadLocal() @@ -115,27 +129,27 @@ class SynchronizerImpl(object): else: return self._state.get() state = property(state) - + def release_read_lock(self): state = self.state - if state.writing: + if state.writing: raise LockError("lock is in writing state") - if not state.reading: + if not state.reading: raise LockError("lock is not in reading state") - + if state.reentrantcount == 1: self.do_release_read_lock() state.reading = False state.reentrantcount -= 1 - - def acquire_read_lock(self, wait = True): + + def acquire_read_lock(self, wait=True): state = self.state - if state.writing: + if state.writing: raise LockError("lock is in writing state") - + if state.reentrantcount == 0: x = self.do_acquire_read_lock(wait) if (wait or x): @@ -145,13 +159,13 @@ class SynchronizerImpl(object): elif state.reading: state.reentrantcount += 1 return True - + def release_write_lock(self): state = self.state - if state.reading: + if state.reading: raise LockError("lock is in reading state") - if not state.writing: + if not state.writing: raise LockError("lock is not in writing state") if state.reentrantcount == 1: @@ -159,18 +173,18 @@ class SynchronizerImpl(object): state.writing = False state.reentrantcount -= 1 - + release = release_write_lock - - def acquire_write_lock(self, wait = True): + + def acquire_write_lock(self, wait=True): state = self.state - if state.reading: + if state.reading: raise LockError("lock is in reading state") - + if state.reentrantcount == 0: x = self.do_acquire_write_lock(wait) - if (wait or x): + if (wait or x): state.reentrantcount += 1 state.writing = True return x @@ -182,56 +196,47 @@ class SynchronizerImpl(object): def do_release_read_lock(self): raise NotImplementedError() - + def do_acquire_read_lock(self): raise NotImplementedError() - + def do_release_write_lock(self): raise NotImplementedError() - + def do_acquire_write_lock(self): raise NotImplementedError() class FileSynchronizer(SynchronizerImpl): - """a synchronizer which locks using flock(). - - Adapted for Python/multithreads from Apache::Session::Lock::File, - http://search.cpan.org/src/CWEST/Apache-Session-1.81/Session/Lock/File.pm - - This module does not unlink temporary files, - because it interferes with proper locking. This can cause - problems on certain systems (Linux) whose file systems (ext2) do not - perform well with lots of files in one directory. To prevent this - you should use a script to clean out old files from your lock directory. - + """A synchronizer which locks using flock(). + """ def __init__(self, identifier, lock_dir): super(FileSynchronizer, self).__init__() self._filedescriptor = util.ThreadLocal() - + if lock_dir is None: lock_dir = tempfile.gettempdir() else: lock_dir = lock_dir self.filename = util.encoded_path( - lock_dir, - [identifier], + lock_dir, + [identifier], extension='.lock' ) def _filedesc(self): return self._filedescriptor.get() _filedesc = property(_filedesc) - + def _open(self, mode): filedescriptor = self._filedesc if filedescriptor is None: filedescriptor = os.open(self.filename, mode) self._filedescriptor.put(filedescriptor) return filedescriptor - + def do_acquire_read_lock(self, wait): filedescriptor = self._open(os.O_CREAT | os.O_RDONLY) if not wait: @@ -259,13 +264,13 @@ class FileSynchronizer(SynchronizerImpl): else: fcntl.flock(filedescriptor, fcntl.LOCK_EX) return True - + def do_release_read_lock(self): self._release_all_locks() - + def do_release_write_lock(self): self._release_all_locks() - + def _release_all_locks(self): filedescriptor = self._filedesc if filedescriptor is not None: @@ -276,7 +281,7 @@ class FileSynchronizer(SynchronizerImpl): class ConditionSynchronizer(SynchronizerImpl): """a synchronizer using a Condition.""" - + def __init__(self, identifier): super(ConditionSynchronizer, self).__init__() @@ -289,7 +294,7 @@ class ConditionSynchronizer(SynchronizerImpl): # condition object to lock on self.condition = _threading.Condition(_threading.Lock()) - def do_acquire_read_lock(self, wait = True): + def do_acquire_read_lock(self, wait=True): self.condition.acquire() try: # see if a synchronous operation is waiting to start @@ -306,15 +311,15 @@ class ConditionSynchronizer(SynchronizerImpl): finally: self.condition.release() - if not wait: + if not wait: return True - + def do_release_read_lock(self): self.condition.acquire() try: self.async -= 1 - - # check if we are the last asynchronous reader thread + + # check if we are the last asynchronous reader thread # out the door. if self.async == 0: # yes. so if a sync operation is waiting, notifyAll to wake @@ -326,13 +331,13 @@ class ConditionSynchronizer(SynchronizerImpl): "release_read_locks called") finally: self.condition.release() - - def do_acquire_write_lock(self, wait = True): + + def do_acquire_write_lock(self, wait=True): self.condition.acquire() try: # here, we are not a synchronous reader, and after returning, # assuming waiting or immediate availability, we will be. - + if wait: # if another sync is working, wait while self.current_sync_operation is not None: @@ -342,8 +347,8 @@ class ConditionSynchronizer(SynchronizerImpl): # we dont want to wait, so forget it if self.current_sync_operation is not None: return False - - # establish ourselves as the current sync + + # establish ourselves as the current sync # this indicates to other read/write operations # that they should wait until this is None again self.current_sync_operation = _threading.currentThread() @@ -359,8 +364,8 @@ class ConditionSynchronizer(SynchronizerImpl): return False finally: self.condition.release() - - if not wait: + + if not wait: return True def do_release_write_lock(self): @@ -370,7 +375,7 @@ class ConditionSynchronizer(SynchronizerImpl): raise LockError("Synchronizer error - current thread doesnt " "have the write lock") - # reset the current sync operation so + # reset the current sync operation so # another can get it self.current_sync_operation = None diff --git a/module/lib/beaker/util.py b/module/lib/beaker/util.py index 04c9617c5..c7002cd92 100644 --- a/module/lib/beaker/util.py +++ b/module/lib/beaker/util.py @@ -9,14 +9,16 @@ except ImportError: from datetime import datetime, timedelta import os +import re import string import types import weakref import warnings import sys +import inspect py3k = getattr(sys, 'py3kwarning', False) or sys.version_info >= (3, 0) -py24 = sys.version_info < (2,5) +py24 = sys.version_info < (2, 5) jython = sys.platform.startswith('java') if py3k or jython: @@ -25,11 +27,56 @@ else: import cPickle as pickle from beaker.converters import asbool +from beaker import exceptions from threading import local as _tlocal -__all__ = ["ThreadLocal", "Registry", "WeakValuedRegistry", "SyncDict", - "encoded_path", "verify_directory"] +__all__ = ["ThreadLocal", "WeakValuedRegistry", "SyncDict", "encoded_path", + "verify_directory"] + + +def function_named(fn, name): + """Return a function with a given __name__. + + Will assign to __name__ and return the original function if possible on + the Python implementation, otherwise a new function will be constructed. + + """ + fn.__name__ = name + return fn + + +def skip_if(predicate, reason=None): + """Skip a test if predicate is true.""" + reason = reason or predicate.__name__ + + from nose import SkipTest + + def decorate(fn): + fn_name = fn.__name__ + + def maybe(*args, **kw): + if predicate(): + msg = "'%s' skipped: %s" % ( + fn_name, reason) + raise SkipTest(msg) + else: + return fn(*args, **kw) + return function_named(maybe, fn_name) + return decorate + + +def assert_raises(except_cls, callable_, *args, **kw): + """Assert the given exception is raised by the given function + arguments.""" + + try: + callable_(*args, **kw) + success = False + except except_cls: + success = True + + # assert outside the block so it works for AssertionError too ! + assert success, "Callable did not raise an exception" def verify_directory(dir): @@ -45,7 +92,24 @@ def verify_directory(dir): if tries > 5: raise - + +def has_self_arg(func): + """Return True if the given function has a 'self' argument.""" + args = inspect.getargspec(func) + if args and args[0] and args[0][0] in ('self', 'cls'): + return True + else: + return False + + +def warn(msg, stacklevel=3): + """Issue a warning.""" + if isinstance(msg, basestring): + warnings.warn(msg, exceptions.BeakerWarning, stacklevel=stacklevel) + else: + warnings.warn(msg, stacklevel=stacklevel) + + def deprecated(message): def wrapper(fn): def deprecated_method(*args, **kargs): @@ -56,7 +120,8 @@ def deprecated(message): deprecated_method.__doc__ = "%s\n\n%s" % (message, fn.__doc__) return deprecated_method return wrapper - + + class ThreadLocal(object): """stores a value on a per-thread basis""" @@ -64,42 +129,43 @@ class ThreadLocal(object): def __init__(self): self._tlocal = _tlocal() - + def put(self, value): self._tlocal.value = value - + def has(self): return hasattr(self._tlocal, 'value') - + def get(self, default=None): return getattr(self._tlocal, 'value', default) - + def remove(self): del self._tlocal.value - + + class SyncDict(object): """ An efficient/threadsafe singleton map algorithm, a.k.a. "get a value based on this key, and create if not found or not valid" paradigm: - + exists && isvalid ? get : create Designed to work with weakref dictionaries to expect items - to asynchronously disappear from the dictionary. + to asynchronously disappear from the dictionary. Use python 2.3.3 or greater ! a major bug was just fixed in Nov. 2003 that was driving me nuts with garbage collection/weakrefs in this section. - """ + """ def __init__(self): self.mutex = _thread.allocate_lock() self.dict = {} - + def get(self, key, createfunc, *args, **kwargs): try: - if self.has_key(key): + if key in self.dict: return self.dict[key] else: return self.sync_get(key, createfunc, *args, **kwargs) @@ -110,7 +176,7 @@ class SyncDict(object): self.mutex.acquire() try: try: - if self.has_key(key): + if key in self.dict: return self.dict[key] else: return self._create(key, createfunc, *args, **kwargs) @@ -124,16 +190,20 @@ class SyncDict(object): return obj def has_key(self, key): - return self.dict.has_key(key) - + return key in self.dict + def __contains__(self, key): return self.dict.__contains__(key) + def __getitem__(self, key): return self.dict.__getitem__(key) + def __setitem__(self, key, value): self.dict.__setitem__(key, value) + def __delitem__(self, key): return self.dict.__delitem__(key) + def clear(self): self.dict.clear() @@ -143,36 +213,47 @@ class WeakValuedRegistry(SyncDict): self.mutex = _threading.RLock() self.dict = weakref.WeakValueDictionary() -sha1 = None -def encoded_path(root, identifiers, extension = ".enc", depth = 3, +sha1 = None + + +def encoded_path(root, identifiers, extension=".enc", depth=3, digest_filenames=True): - + """Generate a unique file-accessible path from the given list of identifiers starting at the given root directory.""" ident = "_".join(identifiers) - + global sha1 if sha1 is None: from beaker.crypto import sha1 - + if digest_filenames: if py3k: ident = sha1(ident.encode('utf-8')).hexdigest() else: ident = sha1(ident).hexdigest() - + ident = os.path.basename(ident) tokens = [] for d in range(1, depth): tokens.append(ident[0:d]) - + dir = os.path.join(root, *tokens) verify_directory(dir) - + return os.path.join(dir, ident + extension) +def asint(obj): + if isinstance(obj, int): + return obj + elif isinstance(obj, basestring) and re.match(r'^\d+$', obj): + return int(obj) + else: + raise Exception("This is not a proper int") + + def verify_options(opt, types, error): if not isinstance(opt, types): if not isinstance(types, tuple): @@ -185,6 +266,11 @@ def verify_options(opt, types, error): else: if typ == bool: typ = asbool + elif typ == int: + typ = asint + elif typ in (timedelta, datetime): + if not isinstance(opt, typ): + raise Exception("%s requires a timedelta type", typ) opt = typ(opt) coerced = True except: @@ -212,10 +298,12 @@ def coerce_session_params(params): ('lock_dir', (str, types.NoneType), "lock_dir must be a string referring to a " "directory."), ('type', (str, types.NoneType), "Session type must be a string."), - ('cookie_expires', (bool, datetime, timedelta), "Cookie expires was " - "not a boolean, datetime, or timedelta instance."), + ('cookie_expires', (bool, datetime, timedelta, int), "Cookie expires was " + "not a boolean, datetime, int, or timedelta instance."), ('cookie_domain', (str, types.NoneType), "Cookie domain must be a " "string."), + ('cookie_path', (str, types.NoneType), "Cookie path must be a " + "string."), ('id', (str,), "Session id must be a string."), ('key', (str,), "Session key must be a string."), ('secret', (str, types.NoneType), "Session secret must be a string."), @@ -224,11 +312,19 @@ def coerce_session_params(params): ('encrypt_key', (str, types.NoneType), "Session validate_key must be " "a string."), ('secure', (bool, types.NoneType), "Session secure must be a boolean."), + ('httponly', (bool, types.NoneType), "Session httponly must be a boolean."), ('timeout', (int, types.NoneType), "Session timeout must be an " "integer."), ('auto', (bool, types.NoneType), "Session is created if accessed."), + ('webtest_varname', (str, types.NoneType), "Session varname must be " + "a string."), ] - return verify_rules(params, rules) + opts = verify_rules(params, rules) + cookie_expires = opts.get('cookie_expires') + if cookie_expires and isinstance(cookie_expires, int) and \ + not isinstance(cookie_expires, bool): + opts['cookie_expires'] = timedelta(seconds=cookie_expires) + return opts def coerce_cache_params(params): @@ -243,18 +339,63 @@ def coerce_cache_params(params): ('expire', (int, types.NoneType), "expire must be an integer representing " "how many seconds the cache is valid for"), ('regions', (list, tuple, types.NoneType), "Regions must be a " - "comma seperated list of valid regions") + "comma seperated list of valid regions"), + ('key_length', (int, types.NoneType), "key_length must be an integer " + "which indicates the longest a key can be before hashing"), ] return verify_rules(params, rules) +def coerce_memcached_behaviors(behaviors): + rules = [ + ('cas', (bool, int), 'cas must be a boolean or an integer'), + ('no_block', (bool, int), 'no_block must be a boolean or an integer'), + ('receive_timeout', (int,), 'receive_timeout must be an integer'), + ('send_timeout', (int,), 'send_timeout must be an integer'), + ('ketama_hash', (str,), 'ketama_hash must be a string designating ' + 'a valid hashing strategy option'), + ('_poll_timeout', (int,), '_poll_timeout must be an integer'), + ('auto_eject', (bool, int), 'auto_eject must be an integer'), + ('retry_timeout', (int,), 'retry_timeout must be an integer'), + ('_sort_hosts', (bool, int), '_sort_hosts must be an integer'), + ('_io_msg_watermark', (int,), '_io_msg_watermark must be an integer'), + ('ketama', (bool, int), 'ketama must be a boolean or an integer'), + ('ketama_weighted', (bool, int), 'ketama_weighted must be a boolean or ' + 'an integer'), + ('_io_key_prefetch', (int, bool), '_io_key_prefetch must be a boolean ' + 'or an integer'), + ('_hash_with_prefix_key', (bool, int), '_hash_with_prefix_key must be ' + 'a boolean or an integer'), + ('tcp_nodelay', (bool, int), 'tcp_nodelay must be a boolean or an ' + 'integer'), + ('failure_limit', (int,), 'failure_limit must be an integer'), + ('buffer_requests', (bool, int), 'buffer_requests must be a boolean ' + 'or an integer'), + ('_socket_send_size', (int,), '_socket_send_size must be an integer'), + ('num_replicas', (int,), 'num_replicas must be an integer'), + ('remove_failed', (int,), 'remove_failed must be an integer'), + ('_noreply', (bool, int), '_noreply must be a boolean or an integer'), + ('_io_bytes_watermark', (int,), '_io_bytes_watermark must be an ' + 'integer'), + ('_socket_recv_size', (int,), '_socket_recv_size must be an integer'), + ('distribution', (str,), 'distribution must be a string designating ' + 'a valid distribution option'), + ('connect_timeout', (int,), 'connect_timeout must be an integer'), + ('hash', (str,), 'hash must be a string designating a valid hashing ' + 'option'), + ('verify_keys', (bool, int), 'verify_keys must be a boolean or an integer'), + ('dead_timeout', (int,), 'dead_timeout must be an integer') + ] + return verify_rules(behaviors, rules) + + def parse_cache_config_options(config, include_defaults=True): """Parse configuration options and validate for use with the CacheManager""" - + # Load default cache options if include_defaults: - options= dict(type='memory', data_dir=None, expire=None, + options = dict(type='memory', data_dir=None, expire=None, log_file=None) else: options = {} @@ -264,39 +405,58 @@ def parse_cache_config_options(config, include_defaults=True): if key.startswith('cache.'): options[key[6:]] = val coerce_cache_params(options) - + # Set cache to enabled if not turned off - if 'enabled' not in options: + if 'enabled' not in options and include_defaults: options['enabled'] = True - + # Configure region dict if regions are available regions = options.pop('regions', None) if regions: region_configs = {} for region in regions: + if not region: # ensure region name is valid + continue # Setup the default cache options region_options = dict(data_dir=options.get('data_dir'), lock_dir=options.get('lock_dir'), type=options.get('type'), enabled=options['enabled'], - expire=options.get('expire')) - region_len = len(region) + 1 + expire=options.get('expire'), + key_length=options.get('key_length', 250)) + region_prefix = '%s.' % region + region_len = len(region_prefix) for key in options.keys(): - if key.startswith('%s.' % region): + if key.startswith(region_prefix): region_options[key[region_len:]] = options.pop(key) coerce_cache_params(region_options) region_configs[region] = region_options options['cache_regions'] = region_configs return options + +def parse_memcached_behaviors(config): + """Parse behavior options and validate for use with pylibmc + client/PylibMCNamespaceManager, or potentially other memcached + NamespaceManagers that support behaviors""" + behaviors = {} + + for key, val in config.iteritems(): + if key.startswith('behavior.'): + behaviors[key[9:]] = val + + coerce_memcached_behaviors(behaviors) + return behaviors + + def func_namespace(func): """Generates a unique namespace for a function""" kls = None if hasattr(func, 'im_func'): kls = func.im_class func = func.im_func - + if kls: return '%s.%s' % (kls.__module__, kls.__name__) else: - return '%s.%s' % (func.__module__, func.__name__) + return '%s|%s' % (inspect.getsourcefile(func), func.__name__) diff --git a/module/lib/bottle.py b/module/lib/bottle.py index 2c243278e..bcc284c1d 100644 --- a/module/lib/bottle.py +++ b/module/lib/bottle.py @@ -9,14 +9,14 @@ Python Standard Library. Homepage and documentation: http://bottlepy.org/ -Copyright (c) 2011, Marcel Hellkamp. -License: MIT (see LICENSE.txt for details) +Copyright (c) 2013, Marcel Hellkamp. +License: MIT (see LICENSE for details) """ from __future__ import with_statement __author__ = 'Marcel Hellkamp' -__version__ = '0.10.2' +__version__ = '0.12.7' __license__ = 'MIT' # The gevent server adapter needs to patch some modules before they are imported @@ -35,102 +35,116 @@ if __name__ == '__main__': if _cmd_options.server and _cmd_options.server.startswith('gevent'): import gevent.monkey; gevent.monkey.patch_all() -import sys -import base64 -import cgi -import email.utils -import functools -import hmac -import httplib -import imp -import itertools -import mimetypes -import os -import re -import subprocess -import tempfile -import thread -import threading -import time -import warnings - -from Cookie import SimpleCookie +import base64, cgi, email.utils, functools, hmac, imp, itertools, mimetypes,\ + os, re, subprocess, sys, tempfile, threading, time, warnings + from datetime import date as datedate, datetime, timedelta from tempfile import TemporaryFile from traceback import format_exc, print_exc -from urlparse import urljoin, SplitResult as UrlSplitResult - -# Workaround for a bug in some versions of lib2to3 (fixed on CPython 2.7 and 3.2) -import urllib -urlencode = urllib.urlencode -urlquote = urllib.quote -urlunquote = urllib.unquote - -try: from collections import MutableMapping as DictMixin -except ImportError: # pragma: no cover - from UserDict import DictMixin +from inspect import getargspec +from unicodedata import normalize -try: from urlparse import parse_qs -except ImportError: # pragma: no cover - from cgi import parse_qs -try: import cPickle as pickle +try: from simplejson import dumps as json_dumps, loads as json_lds except ImportError: # pragma: no cover - import pickle - -try: from json import dumps as json_dumps, loads as json_lds -except ImportError: # pragma: no cover - try: from simplejson import dumps as json_dumps, loads as json_lds - except ImportError: # pragma: no cover + try: from json import dumps as json_dumps, loads as json_lds + except ImportError: try: from django.utils.simplejson import dumps as json_dumps, loads as json_lds - except ImportError: # pragma: no cover + except ImportError: def json_dumps(data): raise ImportError("JSON support requires Python 2.6 or simplejson.") json_lds = json_dumps -py3k = sys.version_info >= (3,0,0) -NCTextIOWrapper = None -if py3k: # pragma: no cover - json_loads = lambda s: json_lds(touni(s)) - # See Request.POST + +# We now try to fix 2.5/2.6/3.1/3.2 incompatibilities. +# It ain't pretty but it works... Sorry for the mess. + +py = sys.version_info +py3k = py >= (3, 0, 0) +py25 = py < (2, 6, 0) +py31 = (3, 1, 0) <= py < (3, 2, 0) + +# Workaround for the missing "as" keyword in py3k. +def _e(): return sys.exc_info()[1] + +# Workaround for the "print is a keyword/function" Python 2/3 dilemma +# and a fallback for mod_wsgi (resticts stdout/err attribute access) +try: + _stdout, _stderr = sys.stdout.write, sys.stderr.write +except IOError: + _stdout = lambda x: sys.stdout.write(x) + _stderr = lambda x: sys.stderr.write(x) + +# Lots of stdlib and builtin differences. +if py3k: + import http.client as httplib + import _thread as thread + from urllib.parse import urljoin, SplitResult as UrlSplitResult + from urllib.parse import urlencode, quote as urlquote, unquote as urlunquote + urlunquote = functools.partial(urlunquote, encoding='latin1') + from http.cookies import SimpleCookie + from collections import MutableMapping as DictMixin + import pickle from io import BytesIO - def touni(x, enc='utf8', err='strict'): - """ Convert anything to unicode """ - return str(x, enc, err) if isinstance(x, bytes) else str(x) - if sys.version_info < (3,2,0): - from io import TextIOWrapper - class NCTextIOWrapper(TextIOWrapper): - ''' Garbage collecting an io.TextIOWrapper(buffer) instance closes - the wrapped buffer. This subclass keeps it open. ''' - def close(self): pass -else: - json_loads = json_lds + from configparser import ConfigParser + basestring = str + unicode = str + json_loads = lambda s: json_lds(touni(s)) + callable = lambda x: hasattr(x, '__call__') + imap = map + def _raise(*a): raise a[0](a[1]).with_traceback(a[2]) +else: # 2.x + import httplib + import thread + from urlparse import urljoin, SplitResult as UrlSplitResult + from urllib import urlencode, quote as urlquote, unquote as urlunquote + from Cookie import SimpleCookie + from itertools import imap + import cPickle as pickle from StringIO import StringIO as BytesIO - bytes = str - def touni(x, enc='utf8', err='strict'): - """ Convert anything to unicode """ - return x if isinstance(x, unicode) else unicode(str(x), enc, err) - -def tob(data, enc='utf8'): - """ Convert anything to bytes """ - return data.encode(enc) if isinstance(data, unicode) else bytes(data) + from ConfigParser import SafeConfigParser as ConfigParser + if py25: + msg = "Python 2.5 support may be dropped in future versions of Bottle." + warnings.warn(msg, DeprecationWarning) + from UserDict import DictMixin + def next(it): return it.next() + bytes = str + else: # 2.6, 2.7 + from collections import MutableMapping as DictMixin + unicode = unicode + json_loads = json_lds + eval(compile('def _raise(*a): raise a[0], a[1], a[2]', '<py3fix>', 'exec')) +# Some helpers for string/byte handling +def tob(s, enc='utf8'): + return s.encode(enc) if isinstance(s, unicode) else bytes(s) +def touni(s, enc='utf8', err='strict'): + return s.decode(enc, err) if isinstance(s, bytes) else unicode(s) tonat = touni if py3k else tob -tonat.__doc__ = """ Convert anything to native strings """ -def try_update_wrapper(wrapper, wrapped, *a, **ka): - try: # Bug: functools breaks if wrapper is an instane method - functools.update_wrapper(wrapper, wrapped, *a, **ka) +# 3.2 fixes cgi.FieldStorage to accept bytes (which makes a lot of sense). +# 3.1 needs a workaround. +if py31: + from io import TextIOWrapper + class NCTextIOWrapper(TextIOWrapper): + def close(self): pass # Keep wrapped buffer open. + + +# A bug in functools causes it to break if the wrapper is an instance method +def update_wrapper(wrapper, wrapped, *a, **ka): + try: functools.update_wrapper(wrapper, wrapped, *a, **ka) except AttributeError: pass -# Backward compatibility -def depr(message): - warnings.warn(message, DeprecationWarning, stacklevel=3) -# Small helpers -def makelist(data): +# These helpers are used at module level and need to be defined first. +# And yes, I know PEP-8, but sometimes a lower-case classname makes more sense. + +def depr(message, hard=False): + warnings.warn(message, DeprecationWarning, stacklevel=3) + +def makelist(data): # This is just to handy if isinstance(data, (tuple, list, set, dict)): return list(data) elif data: return [data] else: return [] @@ -161,12 +175,13 @@ class DictProperty(object): del getattr(obj, self.attr)[self.key] -class CachedProperty(object): +class cached_property(object): ''' A property that is only computed once per instance and then replaces itself with an ordinary attribute. Deleting the attribute resets the property. ''' def __init__(self, func): + self.__doc__ = getattr(func, '__doc__') self.func = func def __get__(self, obj, cls): @@ -174,10 +189,8 @@ class CachedProperty(object): value = obj.__dict__[self.func.__name__] = self.func(obj) return value -cached_property = CachedProperty - -class lazy_attribute(object): # Does not need configuration -> lower-case name +class lazy_attribute(object): ''' A property that caches itself to the class object. ''' def __init__(self, func): functools.update_wrapper(self, func, updated=[]) @@ -203,35 +216,6 @@ class BottleException(Exception): pass -#TODO: These should subclass BaseRequest - -class HTTPResponse(BottleException): - """ Used to break execution and immediately finish the response """ - def __init__(self, output='', status=200, header=None): - super(BottleException, self).__init__("HTTP Response %d" % status) - self.status = int(status) - self.output = output - self.headers = HeaderDict(header) if header else None - - def apply(self, response): - if self.headers: - for key, value in self.headers.iterallitems(): - response.headers[key] = value - response.status = self.status - - -class HTTPError(HTTPResponse): - """ Used to generate an error page """ - def __init__(self, code=500, output='Unknown Error', exception=None, - traceback=None, header=None): - super(HTTPError, self).__init__(output, code, header) - self.exception = exception - self.traceback = traceback - - def __repr__(self): - return template(ERROR_PAGE_TEMPLATE, e=self) - - @@ -251,11 +235,22 @@ class RouteReset(BottleException): class RouterUnknownModeError(RouteError): pass + class RouteSyntaxError(RouteError): - """ The route parser found something not supported by this router """ + """ The route parser found something not supported by this router. """ + class RouteBuildError(RouteError): - """ The route could not been built """ + """ The route could not be built. """ + + +def _re_flatten(p): + ''' Turn all capturing groups in a regular expression pattern into + non-capturing groups. ''' + if '(' not in p: return p + return re.sub(r'(\\*)(\(\?P<[^>]+>|\((?!\?))', + lambda m: m.group(0) if len(m.group(1)) % 2 else m.group(1) + '(?:', p) + class Router(object): ''' A Router is an ordered collection of route->target pairs. It is used to @@ -270,44 +265,40 @@ class Router(object): ''' default_pattern = '[^/]+' - default_filter = 're' - #: Sorry for the mess. It works. Trust me. - rule_syntax = re.compile('(\\\\*)'\ - '(?:(?::([a-zA-Z_][a-zA-Z_0-9]*)?()(?:#(.*?)#)?)'\ - '|(?:<([a-zA-Z_][a-zA-Z_0-9]*)?(?::([a-zA-Z_]*)'\ - '(?::((?:\\\\.|[^\\\\>]+)+)?)?)?>))') + default_filter = 're' + + #: The current CPython regexp implementation does not allow more + #: than 99 matching groups per regular expression. + _MAX_GROUPS_PER_PATTERN = 99 def __init__(self, strict=False): - self.rules = {} # A {rule: Rule} mapping - self.builder = {} # A rule/name->build_info mapping - self.static = {} # Cache for static routes: {path: {method: target}} - self.dynamic = [] # Cache for dynamic routes. See _compile() + self.rules = [] # All rules in order + self._groups = {} # index of regexes to find them in dyna_routes + self.builder = {} # Data structure for the url builder + self.static = {} # Search structure for static routes + self.dyna_routes = {} + self.dyna_regexes = {} # Search structure for dynamic routes #: If true, static routes are no longer checked first. self.strict_order = strict - self.filters = {'re': self.re_filter, 'int': self.int_filter, - 'float': self.re_filter, 'path': self.path_filter} - - def re_filter(self, conf): - return conf or self.default_pattern, None, None + self.filters = { + 're': lambda conf: + (_re_flatten(conf or self.default_pattern), None, None), + 'int': lambda conf: (r'-?\d+', int, lambda x: str(int(x))), + 'float': lambda conf: (r'-?[\d.]+', float, lambda x: str(float(x))), + 'path': lambda conf: (r'.+?', None, None)} - def int_filter(self, conf): - return r'-?\d+', int, lambda x: str(int(x)) - - def float_filter(self, conf): - return r'-?\d*\.\d+', float, lambda x: str(float(x)) - - def path_filter(self, conf): - return r'.*?', None, None - def add_filter(self, name, func): ''' Add a filter. The provided function is called with the configuration string as parameter and must return a (regexp, to_python, to_url) tuple. The first element is a string, the last two are callables or None. ''' self.filters[name] = func - - def parse_rule(self, rule): - ''' Parses a rule into a (name, filter, conf) token stream. If mode is - None, name contains a static rule part. ''' + + rule_syntax = re.compile('(\\\\*)'\ + '(?:(?::([a-zA-Z_][a-zA-Z_0-9]*)?()(?:#(.*?)#)?)'\ + '|(?:<([a-zA-Z_][a-zA-Z_0-9]*)?(?::([a-zA-Z_]*)'\ + '(?::((?:\\\\.|[^\\\\>]+)+)?)?)?>))') + + def _itertokens(self, rule): offset, prefix = 0, '' for match in self.rule_syntax.finditer(rule): prefix += rule[offset:match.start()] @@ -316,77 +307,95 @@ class Router(object): prefix += match.group(0)[len(g[0]):] offset = match.end() continue - if prefix: yield prefix, None, None - name, filtr, conf = g[1:4] if not g[2] is None else g[4:7] - if not filtr: filtr = self.default_filter - yield name, filtr, conf or None + if prefix: + yield prefix, None, None + name, filtr, conf = g[4:7] if g[2] is None else g[1:4] + yield name, filtr or 'default', conf or None offset, prefix = match.end(), '' if offset <= len(rule) or prefix: yield prefix+rule[offset:], None, None def add(self, rule, method, target, name=None): - ''' Add a new route or replace the target for an existing route. ''' - if rule in self.rules: - self.rules[rule][method] = target - if name: self.builder[name] = self.builder[rule] - return - - target = self.rules[rule] = {method: target} - - # Build pattern and other structures for dynamic routes - anons = 0 # Number of anonymous wildcards - pattern = '' # Regular expression pattern - filters = [] # Lists of wildcard input filters - builder = [] # Data structure for the URL builder + ''' Add a new rule or replace the target for an existing rule. ''' + anons = 0 # Number of anonymous wildcards found + keys = [] # Names of keys + pattern = '' # Regular expression pattern with named groups + filters = [] # Lists of wildcard input filters + builder = [] # Data structure for the URL builder is_static = True - for key, mode, conf in self.parse_rule(rule): + + for key, mode, conf in self._itertokens(rule): if mode: is_static = False + if mode == 'default': mode = self.default_filter mask, in_filter, out_filter = self.filters[mode](conf) - if key: - pattern += '(?P<%s>%s)' % (key, mask) - else: + if not key: pattern += '(?:%s)' % mask - key = 'anon%d' % anons; anons += 1 + key = 'anon%d' % anons + anons += 1 + else: + pattern += '(?P<%s>%s)' % (key, mask) + keys.append(key) if in_filter: filters.append((key, in_filter)) builder.append((key, out_filter or str)) elif key: pattern += re.escape(key) builder.append((None, key)) + self.builder[rule] = builder if name: self.builder[name] = builder if is_static and not self.strict_order: - self.static[self.build(rule)] = target + self.static.setdefault(method, {}) + self.static[method][self.build(rule)] = (target, None) return - def fpat_sub(m): - return m.group(0) if len(m.group(1)) % 2 else m.group(1) + '(?:' - flat_pattern = re.sub(r'(\\*)(\(\?P<[^>]*>|\((?!\?))', fpat_sub, pattern) - try: - re_match = re.compile('^(%s)$' % pattern).match - except re.error, e: - raise RouteSyntaxError("Could not add Route: %s (%s)" % (rule, e)) - - def match(path): - """ Return an url-argument dictionary. """ - url_args = re_match(path).groupdict() - for name, wildcard_filter in filters: - try: - url_args[name] = wildcard_filter(url_args[name]) - except ValueError: - raise HTTPError(400, 'Path has wrong format.') - return url_args + re_pattern = re.compile('^(%s)$' % pattern) + re_match = re_pattern.match + except re.error: + raise RouteSyntaxError("Could not add Route: %s (%s)" % (rule, _e())) + + if filters: + def getargs(path): + url_args = re_match(path).groupdict() + for name, wildcard_filter in filters: + try: + url_args[name] = wildcard_filter(url_args[name]) + except ValueError: + raise HTTPError(400, 'Path has wrong format.') + return url_args + elif re_pattern.groupindex: + def getargs(path): + return re_match(path).groupdict() + else: + getargs = None - try: - combined = '%s|(^%s$)' % (self.dynamic[-1][0].pattern, flat_pattern) - self.dynamic[-1] = (re.compile(combined), self.dynamic[-1][1]) - self.dynamic[-1][1].append((match, target)) - except (AssertionError, IndexError), e: # AssertionError: Too many groups - self.dynamic.append((re.compile('(^%s$)' % flat_pattern), - [(match, target)])) - return match + flatpat = _re_flatten(pattern) + whole_rule = (rule, flatpat, target, getargs) + + if (flatpat, method) in self._groups: + if DEBUG: + msg = 'Route <%s %s> overwrites a previously defined route' + warnings.warn(msg % (method, rule), RuntimeWarning) + self.dyna_routes[method][self._groups[flatpat, method]] = whole_rule + else: + self.dyna_routes.setdefault(method, []).append(whole_rule) + self._groups[flatpat, method] = len(self.dyna_routes[method]) - 1 + + self._compile(method) + + def _compile(self, method): + all_rules = self.dyna_routes[method] + comborules = self.dyna_regexes[method] = [] + maxgroups = self._MAX_GROUPS_PER_PATTERN + for x in range(0, len(all_rules), maxgroups): + some = all_rules[x:x+maxgroups] + combined = (flatpat for (_, flatpat, _, _) in some) + combined = '|'.join('(^%s$)' % flatpat for flatpat in combined) + combined = re.compile(combined).match + rules = [(target, getargs) for (_, _, target, getargs) in some] + comborules.append((combined, rules)) def build(self, _name, *anons, **query): ''' Build an URL by filling the wildcards in a rule. ''' @@ -396,36 +405,50 @@ class Router(object): for i, value in enumerate(anons): query['anon%d'%i] = value url = ''.join([f(query.pop(n)) if n else f for (n,f) in builder]) return url if not query else url+'?'+urlencode(query) - except KeyError, e: - raise RouteBuildError('Missing URL argument: %r' % e.args[0]) + except KeyError: + raise RouteBuildError('Missing URL argument: %r' % _e().args[0]) def match(self, environ): ''' Return a (target, url_agrs) tuple or raise HTTPError(400/404/405). ''' - path, targets, urlargs = environ['PATH_INFO'] or '/', None, {} - if path in self.static: - targets = self.static[path] + verb = environ['REQUEST_METHOD'].upper() + path = environ['PATH_INFO'] or '/' + target = None + if verb == 'HEAD': + methods = ['PROXY', verb, 'GET', 'ANY'] else: - for combined, rules in self.dynamic: - match = combined.match(path) - if not match: continue - getargs, targets = rules[match.lastindex - 1] - urlargs = getargs(path) if getargs else {} - break - - if not targets: - raise HTTPError(404, "Not found: " + repr(environ['PATH_INFO'])) - method = environ['REQUEST_METHOD'].upper() - if method in targets: - return targets[method], urlargs - if method == 'HEAD' and 'GET' in targets: - return targets['GET'], urlargs - if 'ANY' in targets: - return targets['ANY'], urlargs - allowed = [verb for verb in targets if verb != 'ANY'] - if 'GET' in allowed and 'HEAD' not in allowed: - allowed.append('HEAD') - raise HTTPError(405, "Method not allowed.", - header=[('Allow',",".join(allowed))]) + methods = ['PROXY', verb, 'ANY'] + + for method in methods: + if method in self.static and path in self.static[method]: + target, getargs = self.static[method][path] + return target, getargs(path) if getargs else {} + elif method in self.dyna_regexes: + for combined, rules in self.dyna_regexes[method]: + match = combined(path) + if match: + target, getargs = rules[match.lastindex - 1] + return target, getargs(path) if getargs else {} + + # No matching route found. Collect alternative methods for 405 response + allowed = set([]) + nocheck = set(methods) + for method in set(self.static) - nocheck: + if path in self.static[method]: + allowed.add(verb) + for method in set(self.dyna_regexes) - allowed - nocheck: + for combined, rules in self.dyna_regexes[method]: + match = combined(path) + if match: + allowed.add(method) + if allowed: + allow_header = ",".join(sorted(allowed)) + raise HTTPError(405, "Method not allowed.", Allow=allow_header) + + # No matching route and no alternative method found. We give up + raise HTTPError(404, "Not found: " + repr(path)) + + + @@ -435,7 +458,6 @@ class Route(object): turing an URL path rule into a regular expression usable by the Router. ''' - def __init__(self, app, rule, method, callback, name=None, plugins=None, skiplist=None, **config): #: The application this route is installed to. @@ -455,12 +477,12 @@ class Route(object): #: Additional keyword arguments passed to the :meth:`Bottle.route` #: decorator are stored in this dictionary. Used for route-specific #: plugin configuration and meta-data. - self.config = ConfigDict(config) + self.config = ConfigDict().load_dict(config, make_namespaces=True) def __call__(self, *a, **ka): depr("Some APIs changed to return Route() instances instead of"\ " callables. Make sure to use the Route.call method and not to"\ - " call Route instances directly.") + " call Route instances directly.") #0.12 return self.call(*a, **ka) @cached_property @@ -480,7 +502,7 @@ class Route(object): @property def _context(self): - depr('Switch to Plugin API v2 and access the Route object directly.') + depr('Switch to Plugin API v2 and access the Route object directly.') #0.12 return dict(rule=self.rule, method=self.method, callback=self.callback, name=self.name, app=self.app, config=self.config, apply=self.plugins, skip=self.skiplist) @@ -509,9 +531,36 @@ class Route(object): except RouteReset: # Try again with changed configuration. return self._make_callback() if not callback is self.callback: - try_update_wrapper(callback, self.callback) + update_wrapper(callback, self.callback) return callback + def get_undecorated_callback(self): + ''' Return the callback. If the callback is a decorated function, try to + recover the original function. ''' + func = self.callback + func = getattr(func, '__func__' if py3k else 'im_func', func) + closure_attr = '__closure__' if py3k else 'func_closure' + while hasattr(func, closure_attr) and getattr(func, closure_attr): + func = getattr(func, closure_attr)[0].cell_contents + return func + + def get_callback_args(self): + ''' Return a list of argument names the callback (most likely) accepts + as keyword arguments. If the callback is a decorated function, try + to recover the original function before inspection. ''' + return getargspec(self.get_undecorated_callback())[0] + + def get_config(self, key, default=None): + ''' Lookup a config field and return its value, first checking the + route.config, then route.app.config.''' + for conf in (self.config, self.app.conifg): + if key in conf: return conf[key] + return default + + def __repr__(self): + cb = self.get_undecorated_callback() + return '<%s %r %r>' % (self.method, self.rule, cb) + @@ -523,27 +572,81 @@ class Route(object): class Bottle(object): - """ WSGI application """ + """ Each Bottle object represents a single, distinct web application and + consists of routes, callbacks, plugins, resources and configuration. + Instances are callable WSGI applications. + + :param catchall: If true (default), handle all exceptions. Turn off to + let debugging middleware handle exceptions. + """ + + def __init__(self, catchall=True, autojson=True): + + #: A :class:`ConfigDict` for app specific configuration. + self.config = ConfigDict() + self.config._on_change = functools.partial(self.trigger_hook, 'config') + self.config.meta_set('autojson', 'validate', bool) + self.config.meta_set('catchall', 'validate', bool) + self.config['catchall'] = catchall + self.config['autojson'] = autojson + + #: A :class:`ResourceManager` for application files + self.resources = ResourceManager() - def __init__(self, catchall=True, autojson=True, config=None): - """ Create a new bottle instance. - You usually don't do that. Use `bottle.app.push()` instead. - """ self.routes = [] # List of installed :class:`Route` instances. self.router = Router() # Maps requests to :class:`Route` instances. - self.plugins = [] # List of installed plugins. - self.error_handler = {} - #: If true, most exceptions are catched and returned as :exc:`HTTPError` - self.config = ConfigDict(config or {}) - self.catchall = catchall - #: An instance of :class:`HooksPlugin`. Empty by default. - self.hooks = HooksPlugin() - self.install(self.hooks) - if autojson: + + # Core plugins + self.plugins = [] # List of installed plugins. + if self.config['autojson']: self.install(JSONPlugin()) self.install(TemplatePlugin()) + #: If true, most exceptions are caught and returned as :exc:`HTTPError` + catchall = DictProperty('config', 'catchall') + + __hook_names = 'before_request', 'after_request', 'app_reset', 'config' + __hook_reversed = 'after_request' + + @cached_property + def _hooks(self): + return dict((name, []) for name in self.__hook_names) + + def add_hook(self, name, func): + ''' Attach a callback to a hook. Three hooks are currently implemented: + + before_request + Executed once before each request. The request context is + available, but no routing has happened yet. + after_request + Executed once after each request regardless of its outcome. + app_reset + Called whenever :meth:`Bottle.reset` is called. + ''' + if name in self.__hook_reversed: + self._hooks[name].insert(0, func) + else: + self._hooks[name].append(func) + + def remove_hook(self, name, func): + ''' Remove a callback from a hook. ''' + if name in self._hooks and func in self._hooks[name]: + self._hooks[name].remove(func) + return True + + def trigger_hook(self, __name, *args, **kwargs): + ''' Trigger a hook and return a list of results. ''' + return [hook(*args, **kwargs) for hook in self._hooks[__name][:]] + + def hook(self, name): + """ Return a decorator that attaches a callback to a hook. See + :meth:`add_hook` for details.""" + def decorator(func): + self.add_hook(name, func) + return func + return decorator + def mount(self, prefix, app, **options): ''' Mount an application (:class:`Bottle` or plain WSGI) to a specific URL prefix. Example:: @@ -557,31 +660,50 @@ class Bottle(object): All other parameters are passed to the underlying :meth:`route` call. ''' if isinstance(app, basestring): - prefix, app = app, prefix - depr('Parameter order of Bottle.mount() changed.') # 0.10 + depr('Parameter order of Bottle.mount() changed.', True) # 0.10 - parts = filter(None, prefix.split('/')) - if not parts: raise ValueError('Empty path prefix.') - path_depth = len(parts) - options.setdefault('skip', True) - options.setdefault('method', 'ANY') + segments = [p for p in prefix.split('/') if p] + if not segments: raise ValueError('Empty path prefix.') + path_depth = len(segments) - @self.route('/%s/:#.*#' % '/'.join(parts), **options) - def mountpoint(): + def mountpoint_wrapper(): try: request.path_shift(path_depth) - rs = BaseResponse([], 200) - def start_response(status, header): + rs = HTTPResponse([]) + def start_response(status, headerlist, exc_info=None): + if exc_info: + try: + _raise(*exc_info) + finally: + exc_info = None rs.status = status - for name, value in header: rs.add_header(name, value) + for name, value in headerlist: rs.add_header(name, value) return rs.body.append - rs.body = itertools.chain(rs.body, app(request.environ, start_response)) - return HTTPResponse(rs.body, rs.status, rs.headers) + body = app(request.environ, start_response) + if body and rs.body: body = itertools.chain(rs.body, body) + rs.body = body or rs.body + return rs finally: request.path_shift(-path_depth) + options.setdefault('skip', True) + options.setdefault('method', 'PROXY') + options.setdefault('mountpoint', {'prefix': prefix, 'target': app}) + options['callback'] = mountpoint_wrapper + + self.route('/%s/<:re:.*>' % '/'.join(segments), **options) if not prefix.endswith('/'): - self.route('/' + '/'.join(parts), callback=mountpoint, **options) + self.route('/' + '/'.join(segments), **options) + + def merge(self, routes): + ''' Merge the routes of another :class:`Bottle` application or a list of + :class:`Route` objects into this application. The routes keep their + 'owner', meaning that the :data:`Route.app` attribute is not + changed. ''' + if isinstance(routes, Bottle): + routes = routes.routes + for route in routes: + self.add_route(route) def install(self, plugin): ''' Add a plugin to the list of plugins and prepare it for being @@ -620,7 +742,7 @@ class Bottle(object): for route in routes: route.reset() if DEBUG: for route in routes: route.prepare() - self.hooks.trigger('app_reset') + self.trigger_hook('app_reset') def close(self): ''' Close the application and all installed plugins. ''' @@ -628,6 +750,10 @@ class Bottle(object): if hasattr(plugin, 'close'): plugin.close() self.stopped = True + def run(self, **kwargs): + ''' Calls :func:`run` with the same parameters. ''' + run(self, **kwargs) + def match(self, environ): """ Search for a matching route and return a (:class:`Route` , urlargs) tuple. The second value is a dictionary with parameters extracted @@ -640,6 +766,13 @@ class Bottle(object): location = self.router.build(routename, **kargs).lstrip('/') return urljoin(urljoin('/', scriptname), location) + def add_route(self, route): + ''' Add a route object, but do not change the :data:`Route.app` + attribute.''' + self.routes.append(route) + self.router.add(route.rule, route.method, route, name=route.name) + if DEBUG: route.prepare() + def route(self, path=None, method='GET', callback=None, name=None, apply=None, skip=None, **config): """ A decorator to bind a function to a request URL. Example:: @@ -678,9 +811,7 @@ class Bottle(object): verb = verb.upper() route = Route(self, rule, verb, callback, name=name, plugins=plugins, skiplist=skiplist, **config) - self.routes.append(route) - self.router.add(rule, verb, route, name=name) - if DEBUG: route.prepare() + self.add_route(route) return callback return decorator(callback) if callback else decorator @@ -707,44 +838,45 @@ class Bottle(object): return handler return wrapper - def hook(self, name): - """ Return a decorator that attaches a callback to a hook. """ - def wrapper(func): - self.hooks.add(name, func) - return func - return wrapper - - def handle(self, path, method='GET'): - """ (deprecated) Execute the first matching route callback and return - the result. :exc:`HTTPResponse` exceptions are catched and returned. - If :attr:`Bottle.catchall` is true, other exceptions are catched as - well and returned as :exc:`HTTPError` instances (500). - """ - depr("This method will change semantics in 0.10. Try to avoid it.") - if isinstance(path, dict): - return self._handle(path) - return self._handle({'PATH_INFO': path, 'REQUEST_METHOD': method.upper()}) + def default_error_handler(self, res): + return tob(template(ERROR_PAGE_TEMPLATE, e=res)) def _handle(self, environ): + path = environ['bottle.raw_path'] = environ['PATH_INFO'] + if py3k: + try: + environ['PATH_INFO'] = path.encode('latin1').decode('utf8') + except UnicodeError: + return HTTPError(400, 'Invalid path string. Expected UTF-8') + try: - route, args = self.router.match(environ) - environ['route.handle'] = environ['bottle.route'] = route - environ['route.url_args'] = args - return route.call(**args) - except HTTPResponse, r: - return r + environ['bottle.app'] = self + request.bind(environ) + response.bind() + try: + self.trigger_hook('before_request') + route, args = self.router.match(environ) + environ['route.handle'] = route + environ['bottle.route'] = route + environ['route.url_args'] = args + return route.call(**args) + finally: + self.trigger_hook('after_request') + + except HTTPResponse: + return _e() except RouteReset: route.reset() return self._handle(environ) except (KeyboardInterrupt, SystemExit, MemoryError): raise - except Exception, e: + except Exception: if not self.catchall: raise - stacktrace = format_exc(10) + stacktrace = format_exc() environ['wsgi.errors'].write(stacktrace) - return HTTPError(500, "Internal Server Error", e, stacktrace) + return HTTPError(500, "Internal Server Error", _e(), stacktrace) - def _cast(self, out, request, response, peek=None): + def _cast(self, out, peek=None): """ Try to convert the parameter into something WSGI compatible and set correct HTTP headers when possible. Support: False, str, unicode, dict, HTTPResponse, HTTPError, file-like, @@ -753,7 +885,8 @@ class Bottle(object): # Empty output is done here if not out: - response['Content-Length'] = 0 + if 'Content-Length' not in response: + response['Content-Length'] = 0 return [] # Join lists of byte or unicode strings. Mixed lists are NOT supported if isinstance(out, (tuple, list))\ @@ -764,19 +897,18 @@ class Bottle(object): out = out.encode(response.charset) # Byte Strings are just returned if isinstance(out, bytes): - response['Content-Length'] = len(out) + if 'Content-Length' not in response: + response['Content-Length'] = len(out) return [out] # HTTPError or HTTPException (recursive, because they may wrap anything) # TODO: Handle these explicitly in handle() or make them iterable. if isinstance(out, HTTPError): out.apply(response) - out = self.error_handler.get(out.status, repr)(out) - if isinstance(out, HTTPResponse): - depr('Error handlers must not return :exc:`HTTPResponse`.') #0.9 - return self._cast(out, request, response) + out = self.error_handler.get(out.status_code, self.default_error_handler)(out) + return self._cast(out) if isinstance(out, HTTPResponse): out.apply(response) - return self._cast(out.output, request, response) + return self._cast(out.body) # File-like objects. if hasattr(out, 'read'): @@ -787,55 +919,59 @@ class Bottle(object): # Handle Iterables. We peek into them to detect their inner type. try: - out = iter(out) - first = out.next() + iout = iter(out) + first = next(iout) while not first: - first = out.next() + first = next(iout) except StopIteration: - return self._cast('', request, response) - except HTTPResponse, e: - first = e - except Exception, e: - first = HTTPError(500, 'Unhandled exception', e, format_exc(10)) - if isinstance(e, (KeyboardInterrupt, SystemExit, MemoryError))\ - or not self.catchall: - raise + return self._cast('') + except HTTPResponse: + first = _e() + except (KeyboardInterrupt, SystemExit, MemoryError): + raise + except Exception: + if not self.catchall: raise + first = HTTPError(500, 'Unhandled exception', _e(), format_exc()) + # These are the inner types allowed in iterator or generator objects. if isinstance(first, HTTPResponse): - return self._cast(first, request, response) - if isinstance(first, bytes): - return itertools.chain([first], out) - if isinstance(first, unicode): - return itertools.imap(lambda x: x.encode(response.charset), - itertools.chain([first], out)) - return self._cast(HTTPError(500, 'Unsupported response type: %s'\ - % type(first)), request, response) + return self._cast(first) + elif isinstance(first, bytes): + new_iter = itertools.chain([first], iout) + elif isinstance(first, unicode): + encoder = lambda x: x.encode(response.charset) + new_iter = imap(encoder, itertools.chain([first], iout)) + else: + msg = 'Unsupported response type: %s' % type(first) + return self._cast(HTTPError(500, msg)) + if hasattr(out, 'close'): + new_iter = _closeiter(new_iter, out.close) + return new_iter def wsgi(self, environ, start_response): """ The bottle WSGI-interface. """ try: - environ['bottle.app'] = self - request.bind(environ) - response.bind() - out = self._cast(self._handle(environ), request, response) + out = self._cast(self._handle(environ)) # rfc2616 section 4.3 if response._status_code in (100, 101, 204, 304)\ - or request.method == 'HEAD': + or environ['REQUEST_METHOD'] == 'HEAD': if hasattr(out, 'close'): out.close() out = [] - start_response(response._status_line, list(response.iter_headers())) + start_response(response._status_line, response.headerlist) return out except (KeyboardInterrupt, SystemExit, MemoryError): raise - except Exception, e: + except Exception: if not self.catchall: raise err = '<h1>Critical error while processing request: %s</h1>' \ - % environ.get('PATH_INFO', '/') + % html_escape(environ.get('PATH_INFO', '/')) if DEBUG: - err += '<h2>Error:</h2>\n<pre>%s</pre>\n' % repr(e) - err += '<h2>Traceback:</h2>\n<pre>%s</pre>\n' % format_exc(10) - environ['wsgi.errors'].write(err) #TODO: wsgi.error should not get html - start_response('500 INTERNAL SERVER ERROR', [('Content-Type', 'text/html')]) + err += '<h2>Error:</h2>\n<pre>\n%s\n</pre>\n' \ + '<h2>Traceback:</h2>\n<pre>\n%s\n</pre>\n' \ + % (html_escape(repr(_e())), html_escape(format_exc())) + environ['wsgi.errors'].write(err) + headers = [('Content-Type', 'text/html; charset=UTF-8')] + start_response('500 INTERNAL SERVER ERROR', headers, sys.exc_info()) return [tob(err)] def __call__(self, environ, start_response): @@ -851,20 +987,41 @@ class Bottle(object): # HTTP and WSGI Tools ########################################################## ############################################################################### - -class BaseRequest(DictMixin): +class BaseRequest(object): """ A wrapper for WSGI environment dictionaries that adds a lot of - convenient access methods and properties. Most of them are read-only.""" + convenient access methods and properties. Most of them are read-only. + + Adding new attributes to a request actually adds them to the environ + dictionary (as 'bottle.request.ext.<name>'). This is the recommended + way to store and access request-specific data. + """ + + __slots__ = ('environ') #: Maximum size of memory buffer for :attr:`body` in bytes. MEMFILE_MAX = 102400 - def __init__(self, environ): + def __init__(self, environ=None): """ Wrap a WSGI environ dictionary. """ #: The wrapped WSGI environ dictionary. This is the only real attribute. #: All other attributes actually are read-only properties. - self.environ = environ - environ['bottle.request'] = self + self.environ = {} if environ is None else environ + self.environ['bottle.request'] = self + + @DictProperty('environ', 'bottle.app', read_only=True) + def app(self): + ''' Bottle application handling this request. ''' + raise RuntimeError('This request is not connected to an application.') + + @DictProperty('environ', 'bottle.route', read_only=True) + def route(self): + """ The bottle :class:`Route` object that matches this request. """ + raise RuntimeError('This request is not connected to a route.') + + @DictProperty('environ', 'route.url_args', read_only=True) + def url_args(self): + """ The arguments extracted from the URL. """ + raise RuntimeError('This request is not connected to a route.') @property def path(self): @@ -891,8 +1048,8 @@ class BaseRequest(DictMixin): def cookies(self): """ Cookies parsed into a :class:`FormsDict`. Signed cookies are NOT decoded. Use :meth:`get_cookie` if you expect signed cookies. """ - cookies = SimpleCookie(self.environ.get('HTTP_COOKIE','')) - return FormsDict((c.key, c.value) for c in cookies.itervalues()) + cookies = SimpleCookie(self.environ.get('HTTP_COOKIE','')).values() + return FormsDict((c.key, c.value) for c in cookies) def get_cookie(self, key, default=None, secret=None): """ Return the content of a cookie. To read a `Signed Cookie`, the @@ -911,22 +1068,21 @@ class BaseRequest(DictMixin): values are sometimes called "URL arguments" or "GET parameters", but not to be confused with "URL wildcards" as they are provided by the :class:`Router`. ''' - data = parse_qs(self.query_string, keep_blank_values=True) get = self.environ['bottle.get'] = FormsDict() - for key, values in data.iteritems(): - for value in values: - get[key] = value + pairs = _parse_qsl(self.environ.get('QUERY_STRING', '')) + for key, value in pairs: + get[key] = value return get @DictProperty('environ', 'bottle.request.forms', read_only=True) def forms(self): """ Form values parsed from an `url-encoded` or `multipart/form-data` - encoded POST or PUT request body. The result is retuned as a + encoded POST or PUT request body. The result is returned as a :class:`FormsDict`. All keys and values are strings. File uploads are stored separately in :attr:`files`. """ forms = FormsDict() - for name, item in self.POST.iterallitems(): - if not hasattr(item, 'filename'): + for name, item in self.POST.allitems(): + if not isinstance(item, FileUpload): forms[name] = item return forms @@ -935,32 +1091,21 @@ class BaseRequest(DictMixin): """ A :class:`FormsDict` with the combined values of :attr:`query` and :attr:`forms`. File uploads are stored in :attr:`files`. """ params = FormsDict() - for key, value in self.query.iterallitems(): + for key, value in self.query.allitems(): params[key] = value - for key, value in self.forms.iterallitems(): + for key, value in self.forms.allitems(): params[key] = value return params @DictProperty('environ', 'bottle.request.files', read_only=True) def files(self): - """ File uploads parsed from an `url-encoded` or `multipart/form-data` - encoded POST or PUT request body. The values are instances of - :class:`cgi.FieldStorage`. The most important attributes are: - - filename - The filename, if specified; otherwise None; this is the client - side filename, *not* the file name on which it is stored (that's - a temporary file you don't deal with) - file - The file(-like) object from which you can read the data. - value - The value as a *string*; for file uploads, this transparently - reads the file every time you request the value. Do not do this - on big files. + """ File uploads parsed from `multipart/form-data` encoded POST or PUT + request body. The values are instances of :class:`FileUpload`. + """ files = FormsDict() - for name, item in self.POST.iterallitems(): - if hasattr(item, 'filename'): + for name, item in self.POST.allitems(): + if isinstance(item, FileUpload): files[name] = item return files @@ -970,25 +1115,75 @@ class BaseRequest(DictMixin): property holds the parsed content of the request body. Only requests smaller than :attr:`MEMFILE_MAX` are processed to avoid memory exhaustion. ''' - if 'application/json' in self.environ.get('CONTENT_TYPE', '') \ - and 0 < self.content_length < self.MEMFILE_MAX: - return json_loads(self.body.read(self.MEMFILE_MAX)) + ctype = self.environ.get('CONTENT_TYPE', '').lower().split(';')[0] + if ctype == 'application/json': + return json_loads(self._get_body_string()) return None - @DictProperty('environ', 'bottle.request.body', read_only=True) - def _body(self): + def _iter_body(self, read, bufsize): maxread = max(0, self.content_length) - stream = self.environ['wsgi.input'] - body = BytesIO() if maxread < self.MEMFILE_MAX else TemporaryFile(mode='w+b') - while maxread > 0: - part = stream.read(min(maxread, self.MEMFILE_MAX)) + while maxread: + part = read(min(maxread, bufsize)) if not part: break - body.write(part) + yield part maxread -= len(part) + + def _iter_chunked(self, read, bufsize): + err = HTTPError(400, 'Error while parsing chunked transfer body.') + rn, sem, bs = tob('\r\n'), tob(';'), tob('') + while True: + header = read(1) + while header[-2:] != rn: + c = read(1) + header += c + if not c: raise err + if len(header) > bufsize: raise err + size, _, _ = header.partition(sem) + try: + maxread = int(tonat(size.strip()), 16) + except ValueError: + raise err + if maxread == 0: break + buff = bs + while maxread > 0: + if not buff: + buff = read(min(maxread, bufsize)) + part, buff = buff[:maxread], buff[maxread:] + if not part: raise err + yield part + maxread -= len(part) + if read(2) != rn: + raise err + + @DictProperty('environ', 'bottle.request.body', read_only=True) + def _body(self): + body_iter = self._iter_chunked if self.chunked else self._iter_body + read_func = self.environ['wsgi.input'].read + body, body_size, is_temp_file = BytesIO(), 0, False + for part in body_iter(read_func, self.MEMFILE_MAX): + body.write(part) + body_size += len(part) + if not is_temp_file and body_size > self.MEMFILE_MAX: + body, tmp = TemporaryFile(mode='w+b'), body + body.write(tmp.getvalue()) + del tmp + is_temp_file = True self.environ['wsgi.input'] = body body.seek(0) return body + def _get_body_string(self): + ''' read body until content-length or MEMFILE_MAX into a string. Raise + HTTPError(413) on requests that are to large. ''' + clen = self.content_length + if clen > self.MEMFILE_MAX: + raise HTTPError(413, 'Request to large') + if clen < 0: clen = self.MEMFILE_MAX + 1 + data = self.body.read(clen) + if len(data) > self.MEMFILE_MAX: # Fail fast + raise HTTPError(413, 'Request to large') + return data + @property def body(self): """ The HTTP request body as a seek-able file-like object. Depending on @@ -999,6 +1194,11 @@ class BaseRequest(DictMixin): self._body.seek(0) return self._body + @property + def chunked(self): + ''' True if Chunked transfer encoding was. ''' + return 'chunked' in self.environ.get('HTTP_TRANSFER_ENCODING', '').lower() + #: An alias for :attr:`query`. GET = query @@ -1009,25 +1209,35 @@ class BaseRequest(DictMixin): instances of :class:`cgi.FieldStorage` (file uploads). """ post = FormsDict() + # We default to application/x-www-form-urlencoded for everything that + # is not multipart and take the fast path (also: 3.1 workaround) + if not self.content_type.startswith('multipart/'): + pairs = _parse_qsl(tonat(self._get_body_string(), 'latin1')) + for key, value in pairs: + post[key] = value + return post + safe_env = {'QUERY_STRING':''} # Build a safe environment for cgi for key in ('REQUEST_METHOD', 'CONTENT_TYPE', 'CONTENT_LENGTH'): if key in self.environ: safe_env[key] = self.environ[key] - if NCTextIOWrapper: - fb = NCTextIOWrapper(self.body, encoding='ISO-8859-1', newline='\n') - else: - fb = self.body - data = cgi.FieldStorage(fp=fb, environ=safe_env, keep_blank_values=True) - for item in data.list or []: - post[item.name] = item if item.filename else item.value + args = dict(fp=self.body, environ=safe_env, keep_blank_values=True) + if py31: + args['fp'] = NCTextIOWrapper(args['fp'], encoding='utf8', + newline='\n') + elif py3k: + args['encoding'] = 'utf8' + data = cgi.FieldStorage(**args) + self['_cgi.FieldStorage'] = data #http://bugs.python.org/issue18394#msg207958 + data = data.list or [] + for item in data: + if item.filename: + post[item.name] = FileUpload(item.file, item.name, + item.filename, item.headers) + else: + post[item.name] = item.value return post @property - def COOKIES(self): - ''' Alias for :attr:`cookies` (deprecated). ''' - depr('BaseRequest.COOKIES was renamed to BaseRequest.cookies (lowercase).') - return self.cookies - - @property def url(self): """ The full request URI including hostname and scheme. If your app lives behind a reverse proxy or load balancer and you get confusing @@ -1042,7 +1252,7 @@ class BaseRequest(DictMixin): but the fragment is always empty because it is not visible to the server. ''' env = self.environ - http = env.get('wsgi.url_scheme', 'http') + http = env.get('HTTP_X_FORWARDED_PROTO') or env.get('wsgi.url_scheme', 'http') host = env.get('HTTP_X_FORWARDED_HOST') or env.get('HTTP_HOST') if not host: # HTTP 1.1 requires a Host-header. This is for HTTP/1.0 clients. @@ -1091,6 +1301,11 @@ class BaseRequest(DictMixin): return int(self.environ.get('CONTENT_LENGTH') or -1) @property + def content_type(self): + ''' The Content-Type header as a lowercase-string (default: empty). ''' + return self.environ.get('CONTENT_TYPE', '').lower() + + @property def is_xhr(self): ''' True if the request was triggered by a XMLHttpRequest. This only works with JavaScript libraries that support the `X-Requested-With` @@ -1139,6 +1354,7 @@ class BaseRequest(DictMixin): """ Return a new :class:`Request` with a shallow :attr:`environ` copy. """ return Request(self.environ.copy()) + def get(self, value, default=None): return self.environ.get(value, default) def __getitem__(self, key): return self.environ[key] def __delitem__(self, key): self[key] = ""; del(self.environ[key]) def __iter__(self): return iter(self.environ) @@ -1166,27 +1382,41 @@ class BaseRequest(DictMixin): def __repr__(self): return '<%s: %s %s>' % (self.__class__.__name__, self.method, self.url) + def __getattr__(self, name): + ''' Search in self.environ for additional user defined attributes. ''' + try: + var = self.environ['bottle.request.ext.%s'%name] + return var.__get__(self) if hasattr(var, '__get__') else var + except KeyError: + raise AttributeError('Attribute %r not defined.' % name) + + def __setattr__(self, name, value): + if name == 'environ': return object.__setattr__(self, name, value) + self.environ['bottle.request.ext.%s'%name] = value + + + + def _hkey(s): return s.title().replace('_','-') class HeaderProperty(object): def __init__(self, name, reader=None, writer=str, default=''): - self.name, self.reader, self.writer, self.default = name, reader, writer, default + self.name, self.default = name, default + self.reader, self.writer = reader, writer self.__doc__ = 'Current value of the %r header.' % name.title() def __get__(self, obj, cls): if obj is None: return self - value = obj.headers.get(self.name) - return self.reader(value) if (value and self.reader) else (value or self.default) + value = obj.headers.get(self.name, self.default) + return self.reader(value) if self.reader else value def __set__(self, obj, value): - if self.writer: value = self.writer(value) - obj.headers[self.name] = value + obj.headers[self.name] = self.writer(value) def __delete__(self, obj): - if self.name in obj.headers: - del obj.headers[self.name] + del obj.headers[self.name] class BaseResponse(object): @@ -1195,6 +1425,14 @@ class BaseResponse(object): This class does support dict-like case-insensitive item-access to headers, but is NOT a dict. Most notably, iterating over a response yields parts of the body and not the headers. + + :param body: The response body as one of the supported types. + :param status: Either an HTTP status code (e.g. 200) or a status line + including the reason phrase (e.g. '200 OK'). + :param headers: A dictionary or a list of name-value pairs. + + Additional keyword arguments are added to the list of headers. + Underscores in the header name are replaced with dashes. """ default_status = 200 @@ -1208,22 +1446,30 @@ class BaseResponse(object): 'Content-Length', 'Content-Range', 'Content-Type', 'Content-Md5', 'Last-Modified'))} - def __init__(self, body='', status=None, **headers): - self._status_line = None - self._status_code = None - self.body = body + def __init__(self, body='', status=None, headers=None, **more_headers): self._cookies = None - self._headers = {'Content-Type': [self.default_content_type]} + self._headers = {} + self.body = body self.status = status or self.default_status if headers: - for name, value in headers.items(): - self[name] = value - - def copy(self): + if isinstance(headers, dict): + headers = headers.items() + for name, value in headers: + self.add_header(name, value) + if more_headers: + for name, value in more_headers.items(): + self.add_header(name, value) + + def copy(self, cls=None): ''' Returns a copy of self. ''' - copy = Response() + cls = cls or BaseResponse + assert issubclass(cls, BaseResponse) + copy = cls() copy.status = self.status copy._headers = dict((k, v[:]) for (k, v) in self._headers.items()) + if self._cookies: + copy._cookies = SimpleCookie() + copy._cookies.load(self._cookies.output()) return copy def __iter__(self): @@ -1253,26 +1499,24 @@ class BaseResponse(object): raise ValueError('String status line without a reason phrase.') if not 100 <= code <= 999: raise ValueError('Status code out of range.') self._status_code = code - self._status_line = status or ('%d Unknown' % code) + self._status_line = str(status or ('%d Unknown' % code)) def _get_status(self): - depr('BaseReuqest.status will change to return a string in 0.11. Use'\ - ' status_line and status_code to make sure.') #0.10 - return self._status_code + return self._status_line status = property(_get_status, _set_status, None, ''' A writeable property to change the HTTP response status. It accepts either a numeric code (100-999) or a string with a custom reason phrase (e.g. "404 Brain not found"). Both :data:`status_line` and - :data:`status_code` are updates accordingly. The return value is - always a numeric code. ''') + :data:`status_code` are updated accordingly. The return value is + always a status string. ''') del _get_status, _set_status @property def headers(self): ''' An instance of :class:`HeaderDict`, a case-insensitive dict-like view on the response headers. ''' - self.__dict__['headers'] = hdict = HeaderDict() + hdict = HeaderDict() hdict.dict = self._headers return hdict @@ -1286,13 +1530,10 @@ class BaseResponse(object): header with that name, return a default value. ''' return self._headers.get(_hkey(name), [default])[-1] - def set_header(self, name, value, append=False): + def set_header(self, name, value): ''' Create a new response header, replacing any previously defined headers with the same name. ''' - if append: - self.add_header(name, value) - else: - self._headers[_hkey(name)] = [str(value)] + self._headers[_hkey(name)] = [str(value)] def add_header(self, name, value): ''' Add an additional response header, not removing duplicates. ''' @@ -1301,44 +1542,36 @@ class BaseResponse(object): def iter_headers(self): ''' Yield (header, value) tuples, skipping headers that are not allowed with the current response status code. ''' - headers = self._headers.iteritems() - bad_headers = self.bad_headers.get(self.status_code) - if bad_headers: - headers = [h for h in headers if h[0] not in bad_headers] - for name, values in headers: - for value in values: - yield name, value - if self._cookies: - for c in self._cookies.values(): - yield 'Set-Cookie', c.OutputString() - - def wsgiheader(self): - depr('The wsgiheader method is deprecated. See headerlist.') #0.10 return self.headerlist @property def headerlist(self): ''' WSGI conform list of (header, value) tuples. ''' - return list(self.iter_headers()) + out = [] + headers = list(self._headers.items()) + if 'Content-Type' not in self._headers: + headers.append(('Content-Type', [self.default_content_type])) + if self._status_code in self.bad_headers: + bad_headers = self.bad_headers[self._status_code] + headers = [h for h in headers if h[0] not in bad_headers] + out += [(name, val) for name, vals in headers for val in vals] + if self._cookies: + for c in self._cookies.values(): + out.append(('Set-Cookie', c.OutputString())) + return out content_type = HeaderProperty('Content-Type') content_length = HeaderProperty('Content-Length', reader=int) + expires = HeaderProperty('Expires', + reader=lambda x: datetime.utcfromtimestamp(parse_date(x)), + writer=lambda x: http_date(x)) @property - def charset(self): + def charset(self, default='UTF-8'): """ Return the charset specified in the content-type header (default: utf8). """ if 'charset=' in self.content_type: return self.content_type.split('charset=')[-1].split(';')[0].strip() - return 'UTF-8' - - @property - def COOKIES(self): - """ A dict-like SimpleCookie instance. This should not be used directly. - See :meth:`set_cookie`. """ - depr('The COOKIES dict is deprecated. Use `set_cookie()` instead.') # 0.10 - if not self._cookies: - self._cookies = SimpleCookie() - return self._cookies + return default def set_cookie(self, name, value, secret=None, **options): ''' Create a new cookie or replace an old one. If the `secret` parameter is @@ -1384,7 +1617,7 @@ class BaseResponse(object): if len(value) > 4096: raise ValueError('Cookie value to long.') self._cookies[name] = value - for key, value in options.iteritems(): + for key, value in options.items(): if key == 'max_age': if isinstance(value, timedelta): value = value.seconds + value.days * 24 * 3600 @@ -1410,19 +1643,65 @@ class BaseResponse(object): return out -class LocalRequest(BaseRequest, threading.local): - ''' A thread-local subclass of :class:`BaseRequest`. ''' - def __init__(self): pass +def local_property(name=None): + if name: depr('local_property() is deprecated and will be removed.') #0.12 + ls = threading.local() + def fget(self): + try: return ls.var + except AttributeError: + raise RuntimeError("Request context not initialized.") + def fset(self, value): ls.var = value + def fdel(self): del ls.var + return property(fget, fset, fdel, 'Thread-local property') + + +class LocalRequest(BaseRequest): + ''' A thread-local subclass of :class:`BaseRequest` with a different + set of attributes for each thread. There is usually only one global + instance of this class (:data:`request`). If accessed during a + request/response cycle, this instance always refers to the *current* + request (even on a multithreaded server). ''' bind = BaseRequest.__init__ + environ = local_property() -class LocalResponse(BaseResponse, threading.local): - ''' A thread-local subclass of :class:`BaseResponse`. ''' +class LocalResponse(BaseResponse): + ''' A thread-local subclass of :class:`BaseResponse` with a different + set of attributes for each thread. There is usually only one global + instance of this class (:data:`response`). Its attributes are used + to build the HTTP response at the end of the request/response cycle. + ''' bind = BaseResponse.__init__ + _status_line = local_property() + _status_code = local_property() + _cookies = local_property() + _headers = local_property() + body = local_property() -Response = LocalResponse # BC 0.9 -Request = LocalRequest # BC 0.9 +Request = BaseRequest +Response = BaseResponse + + +class HTTPResponse(Response, BottleException): + def __init__(self, body='', status=None, headers=None, **more_headers): + super(HTTPResponse, self).__init__(body, status, headers, **more_headers) + + def apply(self, response): + response._status_code = self._status_code + response._status_line = self._status_line + response._headers = self._headers + response._cookies = self._cookies + response.body = self.body + + +class HTTPError(HTTPResponse): + default_status = 500 + def __init__(self, status=None, body=None, exception=None, traceback=None, + **options): + self.exception = exception + self.traceback = traceback + super(HTTPError, self).__init__(body, status, **options) @@ -1434,6 +1713,7 @@ Request = LocalRequest # BC 0.9 class PluginError(BottleException): pass + class JSONPlugin(object): name = 'json' api = 2 @@ -1441,63 +1721,26 @@ class JSONPlugin(object): def __init__(self, json_dumps=json_dumps): self.json_dumps = json_dumps - def apply(self, callback, context): + def apply(self, callback, route): dumps = self.json_dumps if not dumps: return callback def wrapper(*a, **ka): - rv = callback(*a, **ka) + try: + rv = callback(*a, **ka) + except HTTPError: + rv = _e() + if isinstance(rv, dict): #Attempt to serialize, raises exception on failure json_response = dumps(rv) #Set content type only if serialization succesful response.content_type = 'application/json' return json_response + elif isinstance(rv, HTTPResponse) and isinstance(rv.body, dict): + rv.body = dumps(rv.body) + rv.content_type = 'application/json' return rv - return wrapper - -class HooksPlugin(object): - name = 'hooks' - api = 2 - - _names = 'before_request', 'after_request', 'app_reset' - - def __init__(self): - self.hooks = dict((name, []) for name in self._names) - self.app = None - - def _empty(self): - return not (self.hooks['before_request'] or self.hooks['after_request']) - - def setup(self, app): - self.app = app - - def add(self, name, func): - ''' Attach a callback to a hook. ''' - was_empty = self._empty() - self.hooks.setdefault(name, []).append(func) - if self.app and was_empty and not self._empty(): self.app.reset() - - def remove(self, name, func): - ''' Remove a callback from a hook. ''' - was_empty = self._empty() - if name in self.hooks and func in self.hooks[name]: - self.hooks[name].remove(func) - if self.app and not was_empty and self._empty(): self.app.reset() - - def trigger(self, name, *a, **ka): - ''' Trigger a hook and return a list of results. ''' - hooks = self.hooks[name] - if ka.pop('reversed', False): hooks = hooks[::-1] - return [hook(*a, **ka) for hook in hooks] - - def apply(self, callback, context): - if self._empty(): return callback - def wrapper(*a, **ka): - self.trigger('before_request') - rv = callback(*a, **ka) - self.trigger('after_request', reversed=True) - return rv return wrapper @@ -1513,9 +1756,6 @@ class TemplatePlugin(object): conf = route.config.get('template') if isinstance(conf, (tuple, list)) and len(conf) == 2: return view(conf[0], **conf[1])(callback) - elif isinstance(conf, str) and 'template_opts' in route.config: - depr('The `template_opts` parameter is deprecated.') #0.9 - return view(conf, **route.config['template_opts'])(callback) elif isinstance(conf, str): return view(conf)(callback) else: @@ -1535,13 +1775,13 @@ class _ImportRedirect(object): def find_module(self, fullname, path=None): if '.' not in fullname: return - packname, modname = fullname.rsplit('.', 1) + packname = fullname.rsplit('.', 1)[0] if packname != self.name: return return self def load_module(self, fullname): if fullname in sys.modules: return sys.modules[fullname] - packname, modname = fullname.rsplit('.', 1) + modname = fullname.rsplit('.', 1)[1] realname = self.impmask % modname __import__(realname) module = sys.modules[fullname] = sys.modules[realname] @@ -1566,26 +1806,37 @@ class MultiDict(DictMixin): """ def __init__(self, *a, **k): - self.dict = dict((k, [v]) for k, v in dict(*a, **k).iteritems()) + self.dict = dict((k, [v]) for (k, v) in dict(*a, **k).items()) + def __len__(self): return len(self.dict) def __iter__(self): return iter(self.dict) def __contains__(self, key): return key in self.dict def __delitem__(self, key): del self.dict[key] def __getitem__(self, key): return self.dict[key][-1] def __setitem__(self, key, value): self.append(key, value) - def iterkeys(self): return self.dict.iterkeys() - def itervalues(self): return (v[-1] for v in self.dict.itervalues()) - def iteritems(self): return ((k, v[-1]) for (k, v) in self.dict.iteritems()) - def iterallitems(self): - for key, values in self.dict.iteritems(): - for value in values: - yield key, value - - # 2to3 is not able to fix these automatically. - keys = iterkeys if py3k else lambda self: list(self.iterkeys()) - values = itervalues if py3k else lambda self: list(self.itervalues()) - items = iteritems if py3k else lambda self: list(self.iteritems()) - allitems = iterallitems if py3k else lambda self: list(self.iterallitems()) + def keys(self): return self.dict.keys() + + if py3k: + def values(self): return (v[-1] for v in self.dict.values()) + def items(self): return ((k, v[-1]) for k, v in self.dict.items()) + def allitems(self): + return ((k, v) for k, vl in self.dict.items() for v in vl) + iterkeys = keys + itervalues = values + iteritems = items + iterallitems = allitems + + else: + def values(self): return [v[-1] for v in self.dict.values()] + def items(self): return [(k, v[-1]) for k, v in self.dict.items()] + def iterkeys(self): return self.dict.iterkeys() + def itervalues(self): return (v[-1] for v in self.dict.itervalues()) + def iteritems(self): + return ((k, v[-1]) for k, v in self.dict.iteritems()) + def iterallitems(self): + return ((k, v) for k, vl in self.dict.iteritems() for v in vl) + def allitems(self): + return [(k, v) for k, vl in self.dict.iteritems() for v in vl] def get(self, key, default=None, index=-1, type=None): ''' Return the most recent value for a key. @@ -1600,7 +1851,7 @@ class MultiDict(DictMixin): try: val = self.dict[key][index] return type(val) if type else val - except Exception, e: + except Exception: pass return default @@ -1621,30 +1872,51 @@ class MultiDict(DictMixin): getlist = getall - class FormsDict(MultiDict): ''' This :class:`MultiDict` subclass is used to store request form data. Additionally to the normal dict-like item access methods (which return unmodified data as native strings), this container also supports - attribute-like access to its values. Attribues are automatiically de- or - recoded to match :attr:`input_encoding` (default: 'utf8'). Missing + attribute-like access to its values. Attributes are automatically de- + or recoded to match :attr:`input_encoding` (default: 'utf8'). Missing attributes default to an empty string. ''' #: Encoding used for attribute values. input_encoding = 'utf8' + #: If true (default), unicode strings are first encoded with `latin1` + #: and then decoded to match :attr:`input_encoding`. + recode_unicode = True + + def _fix(self, s, encoding=None): + if isinstance(s, unicode) and self.recode_unicode: # Python 3 WSGI + return s.encode('latin1').decode(encoding or self.input_encoding) + elif isinstance(s, bytes): # Python 2 WSGI + return s.decode(encoding or self.input_encoding) + else: + return s + + def decode(self, encoding=None): + ''' Returns a copy with all keys and values de- or recoded to match + :attr:`input_encoding`. Some libraries (e.g. WTForms) want a + unicode dictionary. ''' + copy = FormsDict() + enc = copy.input_encoding = encoding or self.input_encoding + copy.recode_unicode = False + for key, value in self.allitems(): + copy.append(self._fix(key, enc), self._fix(value, enc)) + return copy def getunicode(self, name, default=None, encoding=None): - value, enc = self.get(name, default), encoding or self.input_encoding + ''' Return the value as a unicode string, or the default. ''' try: - if isinstance(value, bytes): # Python 2 WSGI - return value.decode(enc) - elif isinstance(value, unicode): # Python 3 WSGI - return value.encode('latin1').decode(enc) - return value - except UnicodeError, e: + return self._fix(self[name], encoding) + except (UnicodeError, KeyError): return default - def __getattr__(self, name): return self.getunicode(name, default=u'') + def __getattr__(self, name, default=unicode()): + # Without this guard, pickle generates a cryptic TypeError: + if name.startswith('__') and name.endswith('__'): + return super(FormsDict, self).__getattr__(name) + return self.getunicode(name, default=default) class HeaderDict(MultiDict): @@ -1666,7 +1938,7 @@ class HeaderDict(MultiDict): def get(self, key, default=None, index=-1): return MultiDict.get(self, _hkey(key), default, index) def filter(self, names): - for name in map(_hkey, names): + for name in [_hkey(n) for n in names]: if name in self.dict: del self.dict[name] @@ -1682,7 +1954,7 @@ class WSGIHeaderDict(DictMixin): Currently PEP 333, 444 and 3333 are supported. (PEP 444 is the only one that uses non-native strings.) ''' - #: List of keys that do not have a 'HTTP_' prefix. + #: List of keys that do not have a ``HTTP_`` prefix. cgikeys = ('CONTENT_TYPE', 'CONTENT_LENGTH') def __init__(self, environ): @@ -1720,39 +1992,212 @@ class WSGIHeaderDict(DictMixin): def __contains__(self, key): return self._ekey(key) in self.environ + class ConfigDict(dict): - ''' A dict-subclass with some extras: You can access keys like attributes. - Uppercase attributes create new ConfigDicts and act as name-spaces. - Other missing attributes return None. Calling a ConfigDict updates its - values and returns itself. - - >>> cfg = ConfigDict() - >>> cfg.Namespace.value = 5 - >>> cfg.OtherNamespace(a=1, b=2) - >>> cfg - {'Namespace': {'value': 5}, 'OtherNamespace': {'a': 1, 'b': 2}} + ''' A dict-like configuration storage with additional support for + namespaces, validators, meta-data, on_change listeners and more. + + This storage is optimized for fast read access. Retrieving a key + or using non-altering dict methods (e.g. `dict.get()`) has no overhead + compared to a native dict. ''' + __slots__ = ('_meta', '_on_change') + + class Namespace(DictMixin): + + def __init__(self, config, namespace): + self._config = config + self._prefix = namespace + + def __getitem__(self, key): + depr('Accessing namespaces as dicts is discouraged. ' + 'Only use flat item access: ' + 'cfg["names"]["pace"]["key"] -> cfg["name.space.key"]') #0.12 + return self._config[self._prefix + '.' + key] + + def __setitem__(self, key, value): + self._config[self._prefix + '.' + key] = value + + def __delitem__(self, key): + del self._config[self._prefix + '.' + key] + + def __iter__(self): + ns_prefix = self._prefix + '.' + for key in self._config: + ns, dot, name = key.rpartition('.') + if ns == self._prefix and name: + yield name + + def keys(self): return [x for x in self] + def __len__(self): return len(self.keys()) + def __contains__(self, key): return self._prefix + '.' + key in self._config + def __repr__(self): return '<Config.Namespace %s.*>' % self._prefix + def __str__(self): return '<Config.Namespace %s.*>' % self._prefix + + # Deprecated ConfigDict features + def __getattr__(self, key): + depr('Attribute access is deprecated.') #0.12 + if key not in self and key[0].isupper(): + self[key] = ConfigDict.Namespace(self._config, self._prefix + '.' + key) + if key not in self and key.startswith('__'): + raise AttributeError(key) + return self.get(key) + + def __setattr__(self, key, value): + if key in ('_config', '_prefix'): + self.__dict__[key] = value + return + depr('Attribute assignment is deprecated.') #0.12 + if hasattr(DictMixin, key): + raise AttributeError('Read-only attribute.') + if key in self and self[key] and isinstance(self[key], self.__class__): + raise AttributeError('Non-empty namespace attribute.') + self[key] = value + + def __delattr__(self, key): + if key in self: + val = self.pop(key) + if isinstance(val, self.__class__): + prefix = key + '.' + for key in self: + if key.startswith(prefix): + del self[prefix+key] + + def __call__(self, *a, **ka): + depr('Calling ConfDict is deprecated. Use the update() method.') #0.12 + self.update(*a, **ka) + return self + + def __init__(self, *a, **ka): + self._meta = {} + self._on_change = lambda name, value: None + if a or ka: + depr('Constructor does no longer accept parameters.') #0.12 + self.update(*a, **ka) + + def load_config(self, filename): + ''' Load values from an *.ini style config file. + + If the config file contains sections, their names are used as + namespaces for the values within. The two special sections + ``DEFAULT`` and ``bottle`` refer to the root namespace (no prefix). + ''' + conf = ConfigParser() + conf.read(filename) + for section in conf.sections(): + for key, value in conf.items(section): + if section not in ('DEFAULT', 'bottle'): + key = section + '.' + key + self[key] = value + return self + + def load_dict(self, source, namespace='', make_namespaces=False): + ''' Import values from a dictionary structure. Nesting can be used to + represent namespaces. + + >>> ConfigDict().load_dict({'name': {'space': {'key': 'value'}}}) + {'name.space.key': 'value'} + ''' + stack = [(namespace, source)] + while stack: + prefix, source = stack.pop() + if not isinstance(source, dict): + raise TypeError('Source is not a dict (r)' % type(key)) + for key, value in source.items(): + if not isinstance(key, str): + raise TypeError('Key is not a string (%r)' % type(key)) + full_key = prefix + '.' + key if prefix else key + if isinstance(value, dict): + stack.append((full_key, value)) + if make_namespaces: + self[full_key] = self.Namespace(self, full_key) + else: + self[full_key] = value + return self + def update(self, *a, **ka): + ''' If the first parameter is a string, all keys are prefixed with this + namespace. Apart from that it works just as the usual dict.update(). + Example: ``update('some.namespace', key='value')`` ''' + prefix = '' + if a and isinstance(a[0], str): + prefix = a[0].strip('.') + '.' + a = a[1:] + for key, value in dict(*a, **ka).items(): + self[prefix+key] = value + + def setdefault(self, key, value): + if key not in self: + self[key] = value + return self[key] + + def __setitem__(self, key, value): + if not isinstance(key, str): + raise TypeError('Key has type %r (not a string)' % type(key)) + + value = self.meta_get(key, 'filter', lambda x: x)(value) + if key in self and self[key] is value: + return + self._on_change(key, value) + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + + def clear(self): + for key in self: + del self[key] + + def meta_get(self, key, metafield, default=None): + ''' Return the value of a meta field for a key. ''' + return self._meta.get(key, {}).get(metafield, default) + + def meta_set(self, key, metafield, value): + ''' Set the meta field for a key to a new value. This triggers the + on-change handler for existing keys. ''' + self._meta.setdefault(key, {})[metafield] = value + if key in self: + self[key] = self[key] + + def meta_list(self, key): + ''' Return an iterable of meta field names defined for a key. ''' + return self._meta.get(key, {}).keys() + + # Deprecated ConfigDict features def __getattr__(self, key): + depr('Attribute access is deprecated.') #0.12 if key not in self and key[0].isupper(): - self[key] = ConfigDict() + self[key] = self.Namespace(self, key) + if key not in self and key.startswith('__'): + raise AttributeError(key) return self.get(key) def __setattr__(self, key, value): + if key in self.__slots__: + return dict.__setattr__(self, key, value) + depr('Attribute assignment is deprecated.') #0.12 if hasattr(dict, key): raise AttributeError('Read-only attribute.') - if key in self and self[key] and isinstance(self[key], ConfigDict): + if key in self and self[key] and isinstance(self[key], self.Namespace): raise AttributeError('Non-empty namespace attribute.') self[key] = value def __delattr__(self, key): - if key in self: del self[key] + if key in self: + val = self.pop(key) + if isinstance(val, self.Namespace): + prefix = key + '.' + for key in self: + if key.startswith(prefix): + del self[prefix+key] def __call__(self, *a, **ka): - for key, value in dict(*a, **ka).iteritems(): setattr(self, key, value) + depr('Calling ConfDict is deprecated. Use the update() method.') #0.12 + self.update(*a, **ka) return self + class AppStack(list): """ A stack-like list. Calling it returns the head of the stack. """ @@ -1770,17 +2215,182 @@ class AppStack(list): class WSGIFileWrapper(object): - def __init__(self, fp, buffer_size=1024*64): - self.fp, self.buffer_size = fp, buffer_size - for attr in ('fileno', 'close', 'read', 'readlines'): - if hasattr(fp, attr): setattr(self, attr, getattr(fp, attr)) + def __init__(self, fp, buffer_size=1024*64): + self.fp, self.buffer_size = fp, buffer_size + for attr in ('fileno', 'close', 'read', 'readlines', 'tell', 'seek'): + if hasattr(fp, attr): setattr(self, attr, getattr(fp, attr)) + + def __iter__(self): + buff, read = self.buffer_size, self.read + while True: + part = read(buff) + if not part: return + yield part + + +class _closeiter(object): + ''' This only exists to be able to attach a .close method to iterators that + do not support attribute assignment (most of itertools). ''' + + def __init__(self, iterator, close=None): + self.iterator = iterator + self.close_callbacks = makelist(close) + + def __iter__(self): + return iter(self.iterator) + + def close(self): + for func in self.close_callbacks: + func() + + +class ResourceManager(object): + ''' This class manages a list of search paths and helps to find and open + application-bound resources (files). + + :param base: default value for :meth:`add_path` calls. + :param opener: callable used to open resources. + :param cachemode: controls which lookups are cached. One of 'all', + 'found' or 'none'. + ''' + + def __init__(self, base='./', opener=open, cachemode='all'): + self.opener = open + self.base = base + self.cachemode = cachemode + + #: A list of search paths. See :meth:`add_path` for details. + self.path = [] + #: A cache for resolved paths. ``res.cache.clear()`` clears the cache. + self.cache = {} + + def add_path(self, path, base=None, index=None, create=False): + ''' Add a new path to the list of search paths. Return False if the + path does not exist. + + :param path: The new search path. Relative paths are turned into + an absolute and normalized form. If the path looks like a file + (not ending in `/`), the filename is stripped off. + :param base: Path used to absolutize relative search paths. + Defaults to :attr:`base` which defaults to ``os.getcwd()``. + :param index: Position within the list of search paths. Defaults + to last index (appends to the list). + + The `base` parameter makes it easy to reference files installed + along with a python module or package:: + + res.add_path('./resources/', __file__) + ''' + base = os.path.abspath(os.path.dirname(base or self.base)) + path = os.path.abspath(os.path.join(base, os.path.dirname(path))) + path += os.sep + if path in self.path: + self.path.remove(path) + if create and not os.path.isdir(path): + os.makedirs(path) + if index is None: + self.path.append(path) + else: + self.path.insert(index, path) + self.cache.clear() + return os.path.exists(path) + + def __iter__(self): + ''' Iterate over all existing files in all registered paths. ''' + search = self.path[:] + while search: + path = search.pop() + if not os.path.isdir(path): continue + for name in os.listdir(path): + full = os.path.join(path, name) + if os.path.isdir(full): search.append(full) + else: yield full + + def lookup(self, name): + ''' Search for a resource and return an absolute file path, or `None`. + + The :attr:`path` list is searched in order. The first match is + returend. Symlinks are followed. The result is cached to speed up + future lookups. ''' + if name not in self.cache or DEBUG: + for path in self.path: + fpath = os.path.join(path, name) + if os.path.isfile(fpath): + if self.cachemode in ('all', 'found'): + self.cache[name] = fpath + return fpath + if self.cachemode == 'all': + self.cache[name] = None + return self.cache[name] + + def open(self, name, mode='r', *args, **kwargs): + ''' Find a resource and return a file object, or raise IOError. ''' + fname = self.lookup(name) + if not fname: raise IOError("Resource %r not found." % name) + return self.opener(fname, mode=mode, *args, **kwargs) + + +class FileUpload(object): + + def __init__(self, fileobj, name, filename, headers=None): + ''' Wrapper for file uploads. ''' + #: Open file(-like) object (BytesIO buffer or temporary file) + self.file = fileobj + #: Name of the upload form field + self.name = name + #: Raw filename as sent by the client (may contain unsafe characters) + self.raw_filename = filename + #: A :class:`HeaderDict` with additional headers (e.g. content-type) + self.headers = HeaderDict(headers) if headers else HeaderDict() - def __iter__(self): - read, buff = self.fp.read, self.buffer_size - while True: - part = read(buff) - if not part: break - yield part + content_type = HeaderProperty('Content-Type') + content_length = HeaderProperty('Content-Length', reader=int, default=-1) + + @cached_property + def filename(self): + ''' Name of the file on the client file system, but normalized to ensure + file system compatibility. An empty filename is returned as 'empty'. + + Only ASCII letters, digits, dashes, underscores and dots are + allowed in the final filename. Accents are removed, if possible. + Whitespace is replaced by a single dash. Leading or tailing dots + or dashes are removed. The filename is limited to 255 characters. + ''' + fname = self.raw_filename + if not isinstance(fname, unicode): + fname = fname.decode('utf8', 'ignore') + fname = normalize('NFKD', fname).encode('ASCII', 'ignore').decode('ASCII') + fname = os.path.basename(fname.replace('\\', os.path.sep)) + fname = re.sub(r'[^a-zA-Z0-9-_.\s]', '', fname).strip() + fname = re.sub(r'[-\s]+', '-', fname).strip('.-') + return fname[:255] or 'empty' + + def _copy_file(self, fp, chunk_size=2**16): + read, write, offset = self.file.read, fp.write, self.file.tell() + while 1: + buf = read(chunk_size) + if not buf: break + write(buf) + self.file.seek(offset) + + def save(self, destination, overwrite=False, chunk_size=2**16): + ''' Save file to disk or copy its content to an open file(-like) object. + If *destination* is a directory, :attr:`filename` is added to the + path. Existing files are not overwritten by default (IOError). + + :param destination: File path, directory or file(-like) object. + :param overwrite: If True, replace existing files. (default: False) + :param chunk_size: Bytes to read at a time. (default: 64kb) + ''' + if isinstance(destination, basestring): # Except file-likes here + if os.path.isdir(destination): + destination = os.path.join(destination, self.filename) + if not overwrite and os.path.exists(destination): + raise IOError('File exists.') + with open(destination, 'wb') as fp: + self._copy_file(fp, chunk_size) + else: + self._copy_file(destination, chunk_size) @@ -1792,7 +2402,7 @@ class WSGIFileWrapper(object): ############################################################################### -def abort(code=500, text='Unknown Error: Application stopped.'): +def abort(code=500, text='Unknown Error.'): """ Aborts execution and causes a HTTP error. """ raise HTTPError(code, text) @@ -1800,21 +2410,48 @@ def abort(code=500, text='Unknown Error: Application stopped.'): def redirect(url, code=None): """ Aborts execution and causes a 303 or 302 redirect, depending on the HTTP protocol version. """ - if code is None: + if not code: code = 303 if request.get('SERVER_PROTOCOL') == "HTTP/1.1" else 302 - location = urljoin(request.url, url) - raise HTTPResponse("", status=code, header=dict(Location=location)) + res = response.copy(cls=HTTPResponse) + res.status = code + res.body = "" + res.set_header('Location', urljoin(request.url, url)) + raise res -def static_file(filename, root, mimetype='auto', download=False): +def _file_iter_range(fp, offset, bytes, maxread=1024*1024): + ''' Yield chunks from a range in a file. No chunk is bigger than maxread.''' + fp.seek(offset) + while bytes > 0: + part = fp.read(min(bytes, maxread)) + if not part: break + bytes -= len(part) + yield part + + +def static_file(filename, root, mimetype='auto', download=False, charset='UTF-8'): """ Open a file in a safe way and return :exc:`HTTPResponse` with status - code 200, 305, 401 or 404. Set Content-Type, Content-Encoding, - Content-Length and Last-Modified header. Obey If-Modified-Since header - and HEAD requests. + code 200, 305, 403 or 404. The ``Content-Type``, ``Content-Encoding``, + ``Content-Length`` and ``Last-Modified`` headers are set if possible. + Special support for ``If-Modified-Since``, ``Range`` and ``HEAD`` + requests. + + :param filename: Name or path of the file to send. + :param root: Root path for file lookups. Should be an absolute directory + path. + :param mimetype: Defines the content-type header (default: guess from + file extension) + :param download: If True, ask the browser to open a `Save as...` dialog + instead of opening the file with the associated program. You can + specify a custom filename as a string. If not specified, the + original filename is used (default: False). + :param charset: The charset to use for files with a ``text/*`` + mime-type. (default: UTF-8) """ + root = os.path.abspath(root) + os.sep filename = os.path.abspath(os.path.join(root, filename.strip('/\\'))) - header = dict() + headers = dict() if not filename.startswith(root): return HTTPError(403, "Access denied.") @@ -1825,29 +2462,43 @@ def static_file(filename, root, mimetype='auto', download=False): if mimetype == 'auto': mimetype, encoding = mimetypes.guess_type(filename) - if mimetype: header['Content-Type'] = mimetype - if encoding: header['Content-Encoding'] = encoding - elif mimetype: - header['Content-Type'] = mimetype + if encoding: headers['Content-Encoding'] = encoding + + if mimetype: + if mimetype[:5] == 'text/' and charset and 'charset' not in mimetype: + mimetype += '; charset=%s' % charset + headers['Content-Type'] = mimetype if download: download = os.path.basename(filename if download == True else download) - header['Content-Disposition'] = 'attachment; filename="%s"' % download + headers['Content-Disposition'] = 'attachment; filename="%s"' % download stats = os.stat(filename) - header['Content-Length'] = stats.st_size + headers['Content-Length'] = clen = stats.st_size lm = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(stats.st_mtime)) - header['Last-Modified'] = lm + headers['Last-Modified'] = lm ims = request.environ.get('HTTP_IF_MODIFIED_SINCE') if ims: ims = parse_date(ims.split(";")[0].strip()) if ims is not None and ims >= int(stats.st_mtime): - header['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()) - return HTTPResponse(status=304, header=header) + headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()) + return HTTPResponse(status=304, **headers) body = '' if request.method == 'HEAD' else open(filename, 'rb') - return HTTPResponse(body, header=header) + + headers["Accept-Ranges"] = "bytes" + ranges = request.environ.get('HTTP_RANGE') + if 'HTTP_RANGE' in request.environ: + ranges = list(parse_range_header(request.environ['HTTP_RANGE'], clen)) + if not ranges: + return HTTPError(416, "Requested Range Not Satisfiable") + offset, end = ranges[0] + headers["Content-Range"] = "bytes %d-%d/%d" % (offset, end-1, clen) + headers["Content-Length"] = str(end-offset) + if body: body = _file_iter_range(body, offset, end-offset) + return HTTPResponse(body, status=206, **headers) + return HTTPResponse(body, **headers) @@ -1863,8 +2514,17 @@ def debug(mode=True): """ Change the debug level. There is only one debug level supported at the moment.""" global DEBUG + if mode: warnings.simplefilter('default') DEBUG = bool(mode) +def http_date(value): + if isinstance(value, (datedate, datetime)): + value = value.utctimetuple() + elif isinstance(value, (int, float)): + value = time.gmtime(value) + if not isinstance(value, basestring): + value = time.strftime("%a, %d %b %Y %H:%M:%S GMT", value) + return value def parse_date(ims): """ Parse rfc1123, rfc850 and asctime timestamps and return UTC epoch. """ @@ -1874,21 +2534,47 @@ def parse_date(ims): except (TypeError, ValueError, IndexError, OverflowError): return None - def parse_auth(header): """ Parse rfc2617 HTTP authentication header string (basic) and return (user,pass) tuple or None""" try: method, data = header.split(None, 1) if method.lower() == 'basic': - #TODO: Add 2to3 save base64[encode/decode] functions. user, pwd = touni(base64.b64decode(tob(data))).split(':',1) return user, pwd except (KeyError, ValueError): return None +def parse_range_header(header, maxlen=0): + ''' Yield (start, end) ranges parsed from a HTTP Range header. Skip + unsatisfiable ranges. The end index is non-inclusive.''' + if not header or header[:6] != 'bytes=': return + ranges = [r.split('-', 1) for r in header[6:].split(',') if '-' in r] + for start, end in ranges: + try: + if not start: # bytes=-100 -> last 100 bytes + start, end = max(0, maxlen-int(end)), maxlen + elif not end: # bytes=100- -> all but the first 99 bytes + start, end = int(start), maxlen + else: # bytes=100-200 -> bytes 100-200 (inclusive) + start, end = int(start), min(int(end)+1, maxlen) + if 0 <= start < end <= maxlen: + yield start, end + except ValueError: + pass + +def _parse_qsl(qs): + r = [] + for pair in qs.replace(';','&').split('&'): + if not pair: continue + nv = pair.split('=', 1) + if len(nv) != 2: nv.append('') + key = urlunquote(nv[0].replace('+', ' ')) + value = urlunquote(nv[1].replace('+', ' ')) + r.append((key, value)) + return r def _lscmp(a, b): - ''' Compares two strings in a cryptographically save way: + ''' Compares two strings in a cryptographically safe way: Runtime is not affected by length of common prefix. ''' return not sum(0 if x==y else 1 for x, y in zip(a, b)) and len(a) == len(b) @@ -1923,7 +2609,7 @@ def html_escape(string): def html_quote(string): ''' Escape and quote a string to be used as an HTTP attribute.''' - return '"%s"' % html_escape(string).replace('\n','%#10;')\ + return '"%s"' % html_escape(string).replace('\n',' ')\ .replace('\r',' ').replace('\t','	') @@ -1933,18 +2619,17 @@ def yieldroutes(func): takes optional keyword arguments. The output is best described by example:: a() -> '/a' - b(x, y) -> '/b/:x/:y' - c(x, y=5) -> '/c/:x' and '/c/:x/:y' - d(x=5, y=6) -> '/d' and '/d/:x' and '/d/:x/:y' + b(x, y) -> '/b/<x>/<y>' + c(x, y=5) -> '/c/<x>' and '/c/<x>/<y>' + d(x=5, y=6) -> '/d' and '/d/<x>' and '/d/<x>/<y>' """ - import inspect # Expensive module. Only import if necessary. path = '/' + func.__name__.replace('__','/').lstrip('/') - spec = inspect.getargspec(func) + spec = getargspec(func) argc = len(spec[0]) - len(spec[3] or []) - path += ('/:%s' * argc) % tuple(spec[0][:argc]) + path += ('/<%s>' * argc) % tuple(spec[0][:argc]) yield path for arg in spec[0][argc:]: - path += '/:%s' % arg + path += '/<%s>' % arg yield path @@ -1979,41 +2664,24 @@ def path_shift(script_name, path_info, shift=1): return new_script_name, new_path_info -def validate(**vkargs): - """ - Validates and manipulates keyword arguments by user defined callables. - Handles ValueError and missing arguments by raising HTTPError(403). - """ - depr('Use route wildcard filters instead.') - def decorator(func): - @functools.wraps(func) - def wrapper(*args, **kargs): - for key, value in vkargs.iteritems(): - if key not in kargs: - abort(403, 'Missing parameter: %s' % key) - try: - kargs[key] = value(kargs[key]) - except ValueError: - abort(403, 'Wrong parameter format for: %s' % key) - return func(*args, **kargs) - return wrapper - return decorator - - def auth_basic(check, realm="private", text="Access denied"): ''' Callback decorator to require HTTP auth (basic). TODO: Add route(check_auth=...) parameter. ''' def decorator(func): - def wrapper(*a, **ka): - user, password = request.auth or (None, None) - if user is None or not check(user, password): - response.headers['WWW-Authenticate'] = 'Basic realm="%s"' % realm - return HTTPError(401, text) - return func(*a, **ka) - return wrapper + def wrapper(*a, **ka): + user, password = request.auth or (None, None) + if user is None or not check(user, password): + err = HTTPError(401, text) + err.add_header('WWW-Authenticate', 'Basic realm="%s"' % realm) + return err + return func(*a, **ka) + return wrapper return decorator +# Shortcuts for common Bottle methods. +# They all refer to the current default application. + def make_default_app_wrapper(name): ''' Return a callable that relays calls to the current default app. ''' @functools.wraps(getattr(Bottle, name)) @@ -2021,12 +2689,18 @@ def make_default_app_wrapper(name): return getattr(app(), name)(*a, **ka) return wrapper +route = make_default_app_wrapper('route') +get = make_default_app_wrapper('get') +post = make_default_app_wrapper('post') +put = make_default_app_wrapper('put') +delete = make_default_app_wrapper('delete') +error = make_default_app_wrapper('error') +mount = make_default_app_wrapper('mount') +hook = make_default_app_wrapper('hook') +install = make_default_app_wrapper('install') +uninstall = make_default_app_wrapper('uninstall') +url = make_default_app_wrapper('get_url') -for name in '''route get post put delete error mount - hook install uninstall'''.split(): - globals()[name] = make_default_app_wrapper(name) -url = make_default_app_wrapper('get_url') -del name @@ -2040,8 +2714,8 @@ del name class ServerAdapter(object): quiet = False - def __init__(self, host='127.0.0.1', port=8080, **config): - self.options = config + def __init__(self, host='127.0.0.1', port=8080, **options): + self.options = options self.host = host self.port = int(port) @@ -2071,32 +2745,66 @@ class FlupFCGIServer(ServerAdapter): class WSGIRefServer(ServerAdapter): - def run(self, handler): # pragma: no cover - from wsgiref.simple_server import make_server, WSGIRequestHandler - if self.quiet: - class QuietHandler(WSGIRequestHandler): - def log_request(*args, **kw): pass - self.options['handler_class'] = QuietHandler - srv = make_server(self.host, self.port, handler, **self.options) + def run(self, app): # pragma: no cover + from wsgiref.simple_server import WSGIRequestHandler, WSGIServer + from wsgiref.simple_server import make_server + import socket + + class FixedHandler(WSGIRequestHandler): + def address_string(self): # Prevent reverse DNS lookups please. + return self.client_address[0] + def log_request(*args, **kw): + if not self.quiet: + return WSGIRequestHandler.log_request(*args, **kw) + + handler_cls = self.options.get('handler_class', FixedHandler) + server_cls = self.options.get('server_class', WSGIServer) + + if ':' in self.host: # Fix wsgiref for IPv6 addresses. + if getattr(server_cls, 'address_family') == socket.AF_INET: + class server_cls(server_cls): + address_family = socket.AF_INET6 + + srv = make_server(self.host, self.port, app, server_cls, handler_cls) srv.serve_forever() class CherryPyServer(ServerAdapter): def run(self, handler): # pragma: no cover from cherrypy import wsgiserver - server = wsgiserver.CherryPyWSGIServer((self.host, self.port), handler) + self.options['bind_addr'] = (self.host, self.port) + self.options['wsgi_app'] = handler + + certfile = self.options.get('certfile') + if certfile: + del self.options['certfile'] + keyfile = self.options.get('keyfile') + if keyfile: + del self.options['keyfile'] + + server = wsgiserver.CherryPyWSGIServer(**self.options) + if certfile: + server.ssl_certificate = certfile + if keyfile: + server.ssl_private_key = keyfile + try: server.start() finally: server.stop() +class WaitressServer(ServerAdapter): + def run(self, handler): + from waitress import serve + serve(handler, host=self.host, port=self.port) + + class PasteServer(ServerAdapter): def run(self, handler): # pragma: no cover from paste import httpserver - if not self.quiet: - from paste.translogger import TransLogger - handler = TransLogger(handler) + from paste.translogger import TransLogger + handler = TransLogger(handler, setup_console_handler=(not self.quiet)) httpserver.serve(handler, host=self.host, port=str(self.port), **self.options) @@ -2120,8 +2828,8 @@ class FapwsServer(ServerAdapter): evwsgi.start(self.host, port) # fapws3 never releases the GIL. Complain upstream. I tried. No luck. if 'BOTTLE_CHILD' in os.environ and not self.quiet: - print "WARNING: Auto-reloading does not work with Fapws3." - print " (Fapws3 breaks python thread support)" + _stderr("WARNING: Auto-reloading does not work with Fapws3.\n") + _stderr(" (Fapws3 breaks python thread support)\n") evwsgi.set_base_module(base) def app(environ, start_response): environ['wsgi.multiprocess'] = False @@ -2136,7 +2844,7 @@ class TornadoServer(ServerAdapter): import tornado.wsgi, tornado.httpserver, tornado.ioloop container = tornado.wsgi.WSGIContainer(handler) server = tornado.httpserver.HTTPServer(container) - server.listen(port=self.port) + server.listen(port=self.port,address=self.host) tornado.ioloop.IOLoop.instance().start() @@ -2178,16 +2886,30 @@ class DieselServer(ServerAdapter): class GeventServer(ServerAdapter): """ Untested. Options: - * `monkey` (default: True) fixes the stdlib to use greenthreads. * `fast` (default: False) uses libevent's http server, but has some issues: No streaming, no pipelining, no SSL. + * See gevent.wsgi.WSGIServer() documentation for more options. """ def run(self, handler): - from gevent import wsgi as wsgi_fast, pywsgi, monkey, local - if self.options.get('monkey', True): - if not threading.local is local.local: monkey.patch_all() - wsgi = wsgi_fast if self.options.get('fast') else pywsgi - wsgi.WSGIServer((self.host, self.port), handler).serve_forever() + from gevent import wsgi, pywsgi, local + if not isinstance(threading.local(), local.local): + msg = "Bottle requires gevent.monkey.patch_all() (before import)" + raise RuntimeError(msg) + if not self.options.pop('fast', None): wsgi = pywsgi + self.options['log'] = None if self.quiet else 'default' + address = (self.host, self.port) + server = wsgi.WSGIServer(address, handler, **self.options) + if 'BOTTLE_CHILD' in os.environ: + import signal + signal.signal(signal.SIGINT, lambda s, f: server.stop()) + server.serve_forever() + + +class GeventSocketIOServer(ServerAdapter): + def run(self,handler): + from socketio import server + address = (self.host, self.port) + server.SocketIOServer(address, handler, **self.options).serve_forever() class GunicornServer(ServerAdapter): @@ -2212,7 +2934,12 @@ class EventletServer(ServerAdapter): """ Untested """ def run(self, handler): from eventlet import wsgi, listen - wsgi.server(listen((self.host, self.port)), handler) + try: + wsgi.server(listen((self.host, self.port)), handler, + log_output=(not self.quiet)) + except TypeError: + # Fallback, if we have old version of eventlet + wsgi.server(listen((self.host, self.port)), handler) class RocketServer(ServerAdapter): @@ -2232,7 +2959,7 @@ class BjoernServer(ServerAdapter): class AutoServer(ServerAdapter): """ Untested. """ - adapters = [PasteServer, CherryPyServer, TwistedServer, WSGIRefServer] + adapters = [WaitressServer, PasteServer, TwistedServer, CherryPyServer, WSGIRefServer] def run(self, handler): for sa in self.adapters: try: @@ -2244,6 +2971,7 @@ server_names = { 'cgi': CGIServer, 'flup': FlupFCGIServer, 'wsgiref': WSGIRefServer, + 'waitress': WaitressServer, 'cherrypy': CherryPyServer, 'paste': PasteServer, 'fapws3': FapwsServer, @@ -2255,6 +2983,7 @@ server_names = { 'gunicorn': GunicornServer, 'eventlet': EventletServer, 'gevent': GeventServer, + 'geventSocketIO':GeventSocketIOServer, 'rocket': RocketServer, 'bjoern' : BjoernServer, 'auto': AutoServer, @@ -2303,8 +3032,10 @@ def load_app(target): default_app.remove(tmp) # Remove the temporary added default application NORUN = nr_old +_debug = debug def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, - interval=1, reloader=False, quiet=False, plugins=None, **kargs): + interval=1, reloader=False, quiet=False, plugins=None, + debug=None, **kargs): """ Start a server instance. This method blocks until the server terminates. :param app: WSGI application or target string supported by @@ -2324,6 +3055,7 @@ def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, if NORUN: return if reloader and not os.environ.get('BOTTLE_CHILD'): try: + lockfile = None fd, lockfile = tempfile.mkstemp(prefix='bottle.', suffix='.lock') os.close(fd) # We only need this file to exist. We never write to it while os.path.exists(lockfile): @@ -2345,9 +3077,8 @@ def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, os.unlink(lockfile) return - stderr = sys.stderr.write - try: + if debug is not None: _debug(debug) app = app or default_app() if isinstance(app, basestring): app = load_app(app) @@ -2368,9 +3099,9 @@ def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, server.quiet = server.quiet or quiet if not server.quiet: - stderr("Bottle server starting up (using %s)...\n" % repr(server)) - stderr("Listening on http://%s:%d/\n" % (server.host, server.port)) - stderr("Hit Ctrl-C to quit.\n\n") + _stderr("Bottle v%s server starting up (using %s)...\n" % (__version__, repr(server))) + _stderr("Listening on http://%s:%d/\n" % (server.host, server.port)) + _stderr("Hit Ctrl-C to quit.\n\n") if reloader: lockfile = os.environ.get('BOTTLE_LOCKFILE') @@ -2383,12 +3114,15 @@ def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, server.run(app) except KeyboardInterrupt: pass - except (SyntaxError, ImportError): + except (SystemExit, MemoryError): + raise + except: if not reloader: raise - if not getattr(server, 'quiet', False): print_exc() + if not getattr(server, 'quiet', quiet): + print_exc() + time.sleep(interval) sys.exit(3) - finally: - if not getattr(server, 'quiet', False): stderr('Shutdown...\n') + class FileCheckerThread(threading.Thread): @@ -2406,7 +3140,7 @@ class FileCheckerThread(threading.Thread): mtime = lambda path: os.stat(path).st_mtime files = dict() - for module in sys.modules.values(): + for module in list(sys.modules.values()): path = getattr(module, '__file__', '') if path[-4:] in ('.pyo', '.pyc'): path = path[:-1] if path and exists(path): files[path] = mtime(path) @@ -2416,20 +3150,20 @@ class FileCheckerThread(threading.Thread): or mtime(self.lockfile) < time.time() - self.interval - 5: self.status = 'error' thread.interrupt_main() - for path, lmtime in files.iteritems(): + for path, lmtime in list(files.items()): if not exists(path) or mtime(path) > lmtime: self.status = 'reload' thread.interrupt_main() break time.sleep(self.interval) - + def __enter__(self): self.start() - + def __exit__(self, exc_type, exc_val, exc_tb): if not self.status: self.status = 'exit' # silent exit self.join() - return issubclass(exc_type, KeyboardInterrupt) + return exc_type is not None and issubclass(exc_type, KeyboardInterrupt) @@ -2465,7 +3199,7 @@ class BaseTemplate(object): self.name = name self.source = source.read() if hasattr(source, 'read') else source self.filename = source.filename if hasattr(source, 'filename') else None - self.lookup = map(os.path.abspath, lookup) + self.lookup = [os.path.abspath(x) for x in lookup] self.encoding = encoding self.settings = self.settings.copy() # Copy from class variable self.settings.update(settings) # Apply @@ -2481,11 +3215,19 @@ class BaseTemplate(object): def search(cls, name, lookup=[]): """ Search name in all directories specified in lookup. First without, then with common extensions. Return first hit. """ - if os.path.isfile(name): return name + if not lookup: + depr('The template lookup path list should not be empty.') #0.12 + lookup = ['.'] + + if os.path.isabs(name) and os.path.isfile(name): + depr('Absolute template path names are deprecated.') #0.12 + return os.path.abspath(name) + for spath in lookup: - fname = os.path.join(spath, name) - if os.path.isfile(fname): - return fname + spath = os.path.abspath(spath) + os.sep + fname = os.path.abspath(os.path.join(spath, name)) + if not fname.startswith(spath): continue + if os.path.isfile(fname): return fname for ext in cls.extensions: if os.path.isfile('%s.%s' % (fname, ext)): return '%s.%s' % (fname, ext) @@ -2510,8 +3252,8 @@ class BaseTemplate(object): """ Render the template with the specified local variables and return a single byte or unicode string. If it is a byte string, the encoding must match self.encoding. This method must be thread-safe! - Local variables may be provided in dictionaries (*args) - or directly, as keywords (**kwargs). + Local variables may be provided in dictionaries (args) + or directly, as keywords (kwargs). """ raise NotImplementedError @@ -2556,7 +3298,7 @@ class CheetahTemplate(BaseTemplate): class Jinja2Template(BaseTemplate): - def prepare(self, filters=None, tests=None, **kwargs): + def prepare(self, filters=None, tests=None, globals={}, **kwargs): from jinja2 import Environment, FunctionLoader if 'prefix' in kwargs: # TODO: to be removed after a while raise RuntimeError('The keyword argument `prefix` has been removed. ' @@ -2564,6 +3306,7 @@ class Jinja2Template(BaseTemplate): self.env = Environment(loader=FunctionLoader(self.loader), **kwargs) if filters: self.env.filters.update(filters) if tests: self.env.tests.update(tests) + if globals: self.env.globals.update(globals) if self.source: self.tpl = self.env.from_string(self.source) else: @@ -2577,189 +3320,252 @@ class Jinja2Template(BaseTemplate): def loader(self, name): fname = self.search(name, self.lookup) - if fname: - with open(fname, "rb") as f: - return f.read().decode(self.encoding) - - -class SimpleTALTemplate(BaseTemplate): - ''' Untested! ''' - def prepare(self, **options): - from simpletal import simpleTAL - # TODO: add option to load METAL files during render - if self.source: - self.tpl = simpleTAL.compileHTMLTemplate(self.source) - else: - with open(self.filename, 'rb') as fp: - self.tpl = simpleTAL.compileHTMLTemplate(tonat(fp.read())) - - def render(self, *args, **kwargs): - from simpletal import simpleTALES - for dictarg in args: kwargs.update(dictarg) - # TODO: maybe reuse a context instead of always creating one - context = simpleTALES.Context() - for k,v in self.defaults.items(): - context.addGlobal(k, v) - for k,v in kwargs.items(): - context.addGlobal(k, v) - output = StringIO() - self.tpl.expand(context, output) - return output.getvalue() + if not fname: return + with open(fname, "rb") as f: + return f.read().decode(self.encoding) class SimpleTemplate(BaseTemplate): - blocks = ('if', 'elif', 'else', 'try', 'except', 'finally', 'for', 'while', - 'with', 'def', 'class') - dedent_blocks = ('elif', 'else', 'except', 'finally') - - @lazy_attribute - def re_pytokens(cls): - ''' This matches comments and all kinds of quoted strings but does - NOT match comments (#...) within quoted strings. (trust me) ''' - return re.compile(r''' - (''(?!')|""(?!")|'{6}|"{6} # Empty strings (all 4 types) - |'(?:[^\\']|\\.)+?' # Single quotes (') - |"(?:[^\\"]|\\.)+?" # Double quotes (") - |'{3}(?:[^\\]|\\.|\n)+?'{3} # Triple-quoted strings (') - |"{3}(?:[^\\]|\\.|\n)+?"{3} # Triple-quoted strings (") - |\#.* # Comments - )''', re.VERBOSE) - - def prepare(self, escape_func=html_escape, noescape=False, **kwargs): + + def prepare(self, escape_func=html_escape, noescape=False, syntax=None, **ka): self.cache = {} enc = self.encoding self._str = lambda x: touni(x, enc) self._escape = lambda x: escape_func(touni(x, enc)) + self.syntax = syntax if noescape: self._str, self._escape = self._escape, self._str - @classmethod - def split_comment(cls, code): - """ Removes comments (#...) from python code. """ - if '#' not in code: return code - #: Remove comments only (leave quoted strings as they are) - subf = lambda m: '' if m.group(0)[0]=='#' else m.group(0) - return re.sub(cls.re_pytokens, subf, code) - @cached_property def co(self): return compile(self.code, self.filename or '<string>', 'exec') @cached_property def code(self): - stack = [] # Current Code indentation - lineno = 0 # Current line of code - ptrbuffer = [] # Buffer for printable strings and token tuple instances - codebuffer = [] # Buffer for generated python code - multiline = dedent = oneline = False - template = self.source or open(self.filename, 'rb').read() - - def yield_tokens(line): - for i, part in enumerate(re.split(r'\{\{(.*?)\}\}', line)): - if i % 2: - if part.startswith('!'): yield 'RAW', part[1:] - else: yield 'CMD', part - else: yield 'TXT', part - - def flush(): # Flush the ptrbuffer - if not ptrbuffer: return - cline = '' - for line in ptrbuffer: - for token, value in line: - if token == 'TXT': cline += repr(value) - elif token == 'RAW': cline += '_str(%s)' % value - elif token == 'CMD': cline += '_escape(%s)' % value - cline += ', ' - cline = cline[:-2] + '\\\n' - cline = cline[:-2] - if cline[:-1].endswith('\\\\\\\\\\n'): - cline = cline[:-7] + cline[-1] # 'nobr\\\\\n' --> 'nobr' - cline = '_printlist([' + cline + '])' - del ptrbuffer[:] # Do this before calling code() again - code(cline) - - def code(stmt): - for line in stmt.splitlines(): - codebuffer.append(' ' * len(stack) + line.strip()) - - for line in template.splitlines(True): - lineno += 1 - line = line if isinstance(line, unicode)\ - else unicode(line, encoding=self.encoding) - if lineno <= 2: - m = re.search(r"%.*coding[:=]\s*([-\w\.]+)", line) - if m: self.encoding = m.group(1) - if m: line = line.replace('coding','coding (removed)') - if line.strip()[:2].count('%') == 1: - line = line.split('%',1)[1].lstrip() # Full line following the % - cline = self.split_comment(line).strip() - cmd = re.split(r'[^a-zA-Z0-9_]', cline)[0] - flush() # You are actually reading this? Good luck, it's a mess :) - if cmd in self.blocks or multiline: - cmd = multiline or cmd - dedent = cmd in self.dedent_blocks # "else:" - if dedent and not oneline and not multiline: - cmd = stack.pop() - code(line) - oneline = not cline.endswith(':') # "if 1: pass" - multiline = cmd if cline.endswith('\\') else False - if not oneline and not multiline: - stack.append(cmd) - elif cmd == 'end' and stack: - code('#end(%s) %s' % (stack.pop(), line.strip()[3:])) - elif cmd == 'include': - p = cline.split(None, 2)[1:] - if len(p) == 2: - code("_=_include(%s, _stdout, %s)" % (repr(p[0]), p[1])) - elif p: - code("_=_include(%s, _stdout)" % repr(p[0])) - else: # Empty %include -> reverse of %rebase - code("_printlist(_base)") - elif cmd == 'rebase': - p = cline.split(None, 2)[1:] - if len(p) == 2: - code("globals()['_rebase']=(%s, dict(%s))" % (repr(p[0]), p[1])) - elif p: - code("globals()['_rebase']=(%s, {})" % repr(p[0])) - else: - code(line) - else: # Line starting with text (not '%') or '%%' (escaped) - if line.strip().startswith('%%'): - line = line.replace('%%', '%', 1) - ptrbuffer.append(yield_tokens(line)) - flush() - return '\n'.join(codebuffer) + '\n' - - def subtemplate(self, _name, _stdout, *args, **kwargs): - for dictarg in args: kwargs.update(dictarg) + source = self.source + if not source: + with open(self.filename, 'rb') as f: + source = f.read() + try: + source, encoding = touni(source), 'utf8' + except UnicodeError: + depr('Template encodings other than utf8 are no longer supported.') #0.11 + source, encoding = touni(source, 'latin1'), 'latin1' + parser = StplParser(source, encoding=encoding, syntax=self.syntax) + code = parser.translate() + self.encoding = parser.encoding + return code + + def _rebase(self, _env, _name=None, **kwargs): + if _name is None: + depr('Rebase function called without arguments.' + ' You were probably looking for {{base}}?', True) #0.12 + _env['_rebase'] = (_name, kwargs) + + def _include(self, _env, _name=None, **kwargs): + if _name is None: + depr('Rebase function called without arguments.' + ' You were probably looking for {{base}}?', True) #0.12 + env = _env.copy() + env.update(kwargs) if _name not in self.cache: self.cache[_name] = self.__class__(name=_name, lookup=self.lookup) - return self.cache[_name].execute(_stdout, kwargs) + return self.cache[_name].execute(env['_stdout'], env) - def execute(self, _stdout, *args, **kwargs): - for dictarg in args: kwargs.update(dictarg) + def execute(self, _stdout, kwargs): env = self.defaults.copy() - env.update({'_stdout': _stdout, '_printlist': _stdout.extend, - '_include': self.subtemplate, '_str': self._str, - '_escape': self._escape, 'get': env.get, - 'setdefault': env.setdefault, 'defined': env.__contains__}) env.update(kwargs) + env.update({'_stdout': _stdout, '_printlist': _stdout.extend, + 'include': functools.partial(self._include, env), + 'rebase': functools.partial(self._rebase, env), '_rebase': None, + '_str': self._str, '_escape': self._escape, 'get': env.get, + 'setdefault': env.setdefault, 'defined': env.__contains__ }) eval(self.co, env) - if '_rebase' in env: - subtpl, rargs = env['_rebase'] - rargs['_base'] = _stdout[:] #copy stdout + if env.get('_rebase'): + subtpl, rargs = env.pop('_rebase') + rargs['base'] = ''.join(_stdout) #copy stdout del _stdout[:] # clear stdout - return self.subtemplate(subtpl,_stdout,rargs) + return self._include(env, subtpl, **rargs) return env def render(self, *args, **kwargs): """ Render the template using keyword arguments as local variables. """ - for dictarg in args: kwargs.update(dictarg) - stdout = [] - self.execute(stdout, kwargs) + env = {}; stdout = [] + for dictarg in args: env.update(dictarg) + env.update(kwargs) + self.execute(stdout, env) return ''.join(stdout) +class StplSyntaxError(TemplateError): pass + + +class StplParser(object): + ''' Parser for stpl templates. ''' + _re_cache = {} #: Cache for compiled re patterns + # This huge pile of voodoo magic splits python code into 8 different tokens. + # 1: All kinds of python strings (trust me, it works) + _re_tok = '((?m)[urbURB]?(?:\'\'(?!\')|""(?!")|\'{6}|"{6}' \ + '|\'(?:[^\\\\\']|\\\\.)+?\'|"(?:[^\\\\"]|\\\\.)+?"' \ + '|\'{3}(?:[^\\\\]|\\\\.|\\n)+?\'{3}' \ + '|"{3}(?:[^\\\\]|\\\\.|\\n)+?"{3}))' + _re_inl = _re_tok.replace('|\\n','') # We re-use this string pattern later + # 2: Comments (until end of line, but not the newline itself) + _re_tok += '|(#.*)' + # 3,4: Keywords that start or continue a python block (only start of line) + _re_tok += '|^([ \\t]*(?:if|for|while|with|try|def|class)\\b)' \ + '|^([ \\t]*(?:elif|else|except|finally)\\b)' + # 5: Our special 'end' keyword (but only if it stands alone) + _re_tok += '|((?:^|;)[ \\t]*end[ \\t]*(?=(?:%(block_close)s[ \\t]*)?\\r?$|;|#))' + # 6: A customizable end-of-code-block template token (only end of line) + _re_tok += '|(%(block_close)s[ \\t]*(?=$))' + # 7: And finally, a single newline. The 8th token is 'everything else' + _re_tok += '|(\\r?\\n)' + # Match the start tokens of code areas in a template + _re_split = '(?m)^[ \t]*(\\\\?)((%(line_start)s)|(%(block_start)s))(%%?)' + # Match inline statements (may contain python strings) + _re_inl = '%%(inline_start)s((?:%s|[^\'"\n]*?)+)%%(inline_end)s' % _re_inl + + default_syntax = '<% %> % {{ }}' + + def __init__(self, source, syntax=None, encoding='utf8'): + self.source, self.encoding = touni(source, encoding), encoding + self.set_syntax(syntax or self.default_syntax) + self.code_buffer, self.text_buffer = [], [] + self.lineno, self.offset = 1, 0 + self.indent, self.indent_mod = 0, 0 + + def get_syntax(self): + ''' Tokens as a space separated string (default: <% %> % {{ }}) ''' + return self._syntax + + def set_syntax(self, syntax): + self._syntax = syntax + self._tokens = syntax.split() + if not syntax in self._re_cache: + names = 'block_start block_close line_start inline_start inline_end' + etokens = map(re.escape, self._tokens) + pattern_vars = dict(zip(names.split(), etokens)) + patterns = (self._re_split, self._re_tok, self._re_inl) + patterns = [re.compile(p%pattern_vars) for p in patterns] + self._re_cache[syntax] = patterns + self.re_split, self.re_tok, self.re_inl = self._re_cache[syntax] + + syntax = property(get_syntax, set_syntax) + + def translate(self): + if self.offset: raise RuntimeError('Parser is a one time instance.') + while True: + m = self.re_split.search(self.source[self.offset:]) + if m: + text = self.source[self.offset:self.offset+m.start()] + self.text_buffer.append(text) + self.offset += m.end() + if m.group(1): # New escape syntax + line, sep, _ = self.source[self.offset:].partition('\n') + self.text_buffer.append(m.group(2)+m.group(5)+line+sep) + self.offset += len(line+sep)+1 + continue + elif m.group(5): # Old escape syntax + depr('Escape code lines with a backslash.') #0.12 + line, sep, _ = self.source[self.offset:].partition('\n') + self.text_buffer.append(m.group(2)+line+sep) + self.offset += len(line+sep)+1 + continue + self.flush_text() + self.read_code(multiline=bool(m.group(4))) + else: break + self.text_buffer.append(self.source[self.offset:]) + self.flush_text() + return ''.join(self.code_buffer) + + def read_code(self, multiline): + code_line, comment = '', '' + while True: + m = self.re_tok.search(self.source[self.offset:]) + if not m: + code_line += self.source[self.offset:] + self.offset = len(self.source) + self.write_code(code_line.strip(), comment) + return + code_line += self.source[self.offset:self.offset+m.start()] + self.offset += m.end() + _str, _com, _blk1, _blk2, _end, _cend, _nl = m.groups() + if code_line and (_blk1 or _blk2): # a if b else c + code_line += _blk1 or _blk2 + continue + if _str: # Python string + code_line += _str + elif _com: # Python comment (up to EOL) + comment = _com + if multiline and _com.strip().endswith(self._tokens[1]): + multiline = False # Allow end-of-block in comments + elif _blk1: # Start-block keyword (if/for/while/def/try/...) + code_line, self.indent_mod = _blk1, -1 + self.indent += 1 + elif _blk2: # Continue-block keyword (else/elif/except/...) + code_line, self.indent_mod = _blk2, -1 + elif _end: # The non-standard 'end'-keyword (ends a block) + self.indent -= 1 + elif _cend: # The end-code-block template token (usually '%>') + if multiline: multiline = False + else: code_line += _cend + else: # \n + self.write_code(code_line.strip(), comment) + self.lineno += 1 + code_line, comment, self.indent_mod = '', '', 0 + if not multiline: + break + + def flush_text(self): + text = ''.join(self.text_buffer) + del self.text_buffer[:] + if not text: return + parts, pos, nl = [], 0, '\\\n'+' '*self.indent + for m in self.re_inl.finditer(text): + prefix, pos = text[pos:m.start()], m.end() + if prefix: + parts.append(nl.join(map(repr, prefix.splitlines(True)))) + if prefix.endswith('\n'): parts[-1] += nl + parts.append(self.process_inline(m.group(1).strip())) + if pos < len(text): + prefix = text[pos:] + lines = prefix.splitlines(True) + if lines[-1].endswith('\\\\\n'): lines[-1] = lines[-1][:-3] + elif lines[-1].endswith('\\\\\r\n'): lines[-1] = lines[-1][:-4] + parts.append(nl.join(map(repr, lines))) + code = '_printlist((%s,))' % ', '.join(parts) + self.lineno += code.count('\n')+1 + self.write_code(code) + + def process_inline(self, chunk): + if chunk[0] == '!': return '_str(%s)' % chunk[1:] + return '_escape(%s)' % chunk + + def write_code(self, line, comment=''): + line, comment = self.fix_backward_compatibility(line, comment) + code = ' ' * (self.indent+self.indent_mod) + code += line.lstrip() + comment + '\n' + self.code_buffer.append(code) + + def fix_backward_compatibility(self, line, comment): + parts = line.strip().split(None, 2) + if parts and parts[0] in ('include', 'rebase'): + depr('The include and rebase keywords are functions now.') #0.12 + if len(parts) == 1: return "_printlist([base])", comment + elif len(parts) == 2: return "_=%s(%r)" % tuple(parts), comment + else: return "_=%s(%r, %s)" % tuple(parts), comment + if self.lineno <= 2 and not line.strip() and 'coding' in comment: + m = re.match(r"#.*coding[:=]\s*([-\w.]+)", comment) + if m: + depr('PEP263 encoding strings in templates are deprecated.') #0.12 + enc = m.group(1) + self.source = self.source.encode(self.encoding).decode(enc) + self.encoding = enc + return line, comment.replace('coding','coding*') + return line, comment + + def template(*args, **kwargs): ''' Get a rendered template as a string iterator. @@ -2768,26 +3574,26 @@ def template(*args, **kwargs): or directly (as keyword arguments). ''' tpl = args[0] if args else None - template_adapter = kwargs.pop('template_adapter', SimpleTemplate) - if tpl not in TEMPLATES or DEBUG: + adapter = kwargs.pop('template_adapter', SimpleTemplate) + lookup = kwargs.pop('template_lookup', TEMPLATE_PATH) + tplid = (id(lookup), tpl) + if tplid not in TEMPLATES or DEBUG: settings = kwargs.pop('template_settings', {}) - lookup = kwargs.pop('template_lookup', TEMPLATE_PATH) - if isinstance(tpl, template_adapter): - TEMPLATES[tpl] = tpl - if settings: TEMPLATES[tpl].prepare(**settings) + if isinstance(tpl, adapter): + TEMPLATES[tplid] = tpl + if settings: TEMPLATES[tplid].prepare(**settings) elif "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl: - TEMPLATES[tpl] = template_adapter(source=tpl, lookup=lookup, **settings) + TEMPLATES[tplid] = adapter(source=tpl, lookup=lookup, **settings) else: - TEMPLATES[tpl] = template_adapter(name=tpl, lookup=lookup, **settings) - if not TEMPLATES[tpl]: + TEMPLATES[tplid] = adapter(name=tpl, lookup=lookup, **settings) + if not TEMPLATES[tplid]: abort(500, 'Template (%s) not found' % tpl) for dictarg in args[1:]: kwargs.update(dictarg) - return TEMPLATES[tpl].render(kwargs) + return TEMPLATES[tplid].render(kwargs) mako_template = functools.partial(template, template_adapter=MakoTemplate) cheetah_template = functools.partial(template, template_adapter=CheetahTemplate) jinja2_template = functools.partial(template, template_adapter=Jinja2Template) -simpletal_template = functools.partial(template, template_adapter=SimpleTALTemplate) def view(tpl_name, **defaults): @@ -2808,6 +3614,8 @@ def view(tpl_name, **defaults): tplvars = defaults.copy() tplvars.update(result) return template(tpl_name, **tplvars) + elif result is None: + return template(tpl_name, defaults) return result return wrapper return decorator @@ -2815,7 +3623,6 @@ def view(tpl_name, **defaults): mako_view = functools.partial(view, template_adapter=MakoTemplate) cheetah_view = functools.partial(view, template_adapter=CheetahTemplate) jinja2_view = functools.partial(view, template_adapter=Jinja2Template) -simpletal_view = functools.partial(view, template_adapter=SimpleTALTemplate) @@ -2839,17 +3646,16 @@ HTTP_CODES[428] = "Precondition Required" HTTP_CODES[429] = "Too Many Requests" HTTP_CODES[431] = "Request Header Fields Too Large" HTTP_CODES[511] = "Network Authentication Required" -_HTTP_STATUS_LINES = dict((k, '%d %s'%(k,v)) for (k,v) in HTTP_CODES.iteritems()) +_HTTP_STATUS_LINES = dict((k, '%d %s'%(k,v)) for (k,v) in HTTP_CODES.items()) #: The default template used for error pages. Override with @error() ERROR_PAGE_TEMPLATE = """ -%try: - %from bottle import DEBUG, HTTP_CODES, request, touni - %status_name = HTTP_CODES.get(e.status, 'Unknown').title() +%%try: + %%from %s import DEBUG, HTTP_CODES, request, touni <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html> <head> - <title>Error {{e.status}}: {{status_name}}</title> + <title>Error: {{e.status}}</title> <style type="text/css"> html {background-color: #eee; font-family: sans;} body {background-color: #fff; border: 1px solid #ddd; @@ -2858,31 +3664,34 @@ ERROR_PAGE_TEMPLATE = """ </style> </head> <body> - <h1>Error {{e.status}}: {{status_name}}</h1> + <h1>Error: {{e.status}}</h1> <p>Sorry, the requested URL <tt>{{repr(request.url)}}</tt> caused an error:</p> - <pre>{{e.output}}</pre> - %if DEBUG and e.exception: + <pre>{{e.body}}</pre> + %%if DEBUG and e.exception: <h2>Exception:</h2> <pre>{{repr(e.exception)}}</pre> - %end - %if DEBUG and e.traceback: + %%end + %%if DEBUG and e.traceback: <h2>Traceback:</h2> <pre>{{e.traceback}}</pre> - %end + %%end </body> </html> -%except ImportError: +%%except ImportError: <b>ImportError:</b> Could not generate the error page. Please add bottle to the import path. -%end -""" +%%end +""" % __name__ -#: A thread-safe instance of :class:`Request` representing the `current` request. -request = Request() +#: A thread-safe instance of :class:`LocalRequest`. If accessed from within a +#: request callback, this instance always refers to the *current* request +#: (even on a multithreaded server). +request = LocalRequest() -#: A thread-safe instance of :class:`Response` used to build the HTTP response. -response = Response() +#: A thread-safe instance of :class:`LocalResponse`. It is used to change the +#: HTTP response for the *current* request. +response = LocalResponse() #: A thread-safe namespace. Not used by Bottle. local = threading.local() @@ -2894,29 +3703,30 @@ app.push() #: A virtual package that redirects import statements. #: Example: ``import bottle.ext.sqlite`` actually imports `bottle_sqlite`. -ext = _ImportRedirect(__name__+'.ext', 'bottle_%s').module +ext = _ImportRedirect('bottle.ext' if __name__ == '__main__' else __name__+".ext", 'bottle_%s').module if __name__ == '__main__': opt, args, parser = _cmd_options, _cmd_args, _cmd_parser if opt.version: - print 'Bottle', __version__; sys.exit(0) + _stdout('Bottle %s\n'%__version__) + sys.exit(0) if not args: parser.print_help() - print '\nError: No application specified.\n' + _stderr('\nError: No application specified.\n') sys.exit(1) - try: - sys.path.insert(0, '.') - sys.modules.setdefault('bottle', sys.modules['__main__']) - except (AttributeError, ImportError), e: - parser.error(e.args[0]) + sys.path.insert(0, '.') + sys.modules.setdefault('bottle', sys.modules['__main__']) + + host, port = (opt.bind or 'localhost'), 8080 + if ':' in host and host.rfind(']') < host.rfind(':'): + host, port = host.rsplit(':', 1) + host = host.strip('[]') + + run(args[0], host=host, port=int(port), server=opt.server, + reloader=opt.reload, plugins=opt.plugin, debug=opt.debug) + - if opt.bind and ':' in opt.bind: - host, port = opt.bind.rsplit(':', 1) - else: - host, port = (opt.bind or 'localhost'), 8080 - debug(opt.debug) - run(args[0], host=host, port=port, server=opt.server, reloader=opt.reload, plugins=opt.plugin) # THE END diff --git a/module/lib/feedparser.py b/module/lib/feedparser.py index a746ed8f5..c78e6a39b 100644 --- a/module/lib/feedparser.py +++ b/module/lib/feedparser.py @@ -1,17 +1,19 @@ -#!/usr/bin/env python """Universal feed parser Handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds -Visit http://feedparser.org/ for the latest version -Visit http://feedparser.org/docs/ for the latest documentation +Visit https://code.google.com/p/feedparser/ for the latest version +Visit http://packages.python.org/feedparser/ for the latest documentation Required: Python 2.4 or later -Recommended: CJKCodecs and iconv_codec <http://cjkpython.i18n.org/> +Recommended: iconv_codec <http://cjkpython.i18n.org/> """ -__version__ = "5.0" -__license__ = """Copyright (c) 2002-2008, Mark Pilgrim, All rights reserved. +__version__ = "5.1.3" +__license__ = """ +Copyright (c) 2010-2012 Kurt McKee <contactme@kurtmckee.org> +Copyright (c) 2002-2008 Mark Pilgrim +All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -42,13 +44,13 @@ __contributors__ = ["Jason Diamond <http://injektilo.org/>", "Sam Ruby <http://intertwingly.net/>", "Ade Oshineye <http://blog.oshineye.com/>", "Martin Pool <http://sourcefrog.net/>", - "Kurt McKee <http://kurtmckee.org/>"] -_debug = 0 + "Kurt McKee <http://kurtmckee.org/>", + "Bernd Schlapsi <https://github.com/brot>",] # HTTP "User-Agent" header to send to servers when downloading feeds. # If you are embedding feedparser in a larger application, you should # change this to your application name and URL. -USER_AGENT = "UniversalFeedParser/%s +http://feedparser.org/" % __version__ +USER_AGENT = "UniversalFeedParser/%s +https://code.google.com/p/feedparser/" % __version__ # HTTP "Accept" header to send to servers when downloading feeds. If you don't # want to send an Accept header, set this to None. @@ -76,6 +78,10 @@ RESOLVE_RELATIVE_URIS = 1 # HTML content, set this to 1. SANITIZE_HTML = 1 +# If you want feedparser to automatically parse microformat content embedded +# in entry contents, set this to 1 +PARSE_MICROFORMATS = 1 + # ---------- Python 3 modules (make it work if possible) ---------- try: import rfc822 @@ -89,34 +95,35 @@ try: except (NameError, AttributeError): import string _maketrans = string.maketrans - + # base64 support for Atom feeds that contain embedded binary data try: import base64, binascii +except ImportError: + base64 = binascii = None +else: # Python 3.1 deprecates decodestring in favor of decodebytes _base64decode = getattr(base64, 'decodebytes', base64.decodestring) -except: - base64 = binascii = None -def _s2bytes(s): - # Convert a UTF-8 str to bytes if the interpreter is Python 3 - try: - return bytes(s, 'utf8') - except (NameError, TypeError): - # In Python 2.5 and below, bytes doesn't exist (NameError) - # In Python 2.6 and above, bytes and str are the same (TypeError) - return s - -def _l2bytes(l): - # Convert a list of ints to bytes if the interpreter is Python 3 - try: - if bytes is not str: - # In Python 2.6 and above, this call won't raise an exception - # but it will return bytes([65]) as '[65]' instead of 'A' - return bytes(l) - raise NameError - except NameError: - return ''.join(map(chr, l)) +# _s2bytes: convert a UTF-8 str to bytes if the interpreter is Python 3 +# _l2bytes: convert a list of ints to bytes if the interpreter is Python 3 +try: + if bytes is str: + # In Python 2.5 and below, bytes doesn't exist (NameError) + # In Python 2.6 and above, bytes and str are the same type + raise NameError +except NameError: + # Python 2 + def _s2bytes(s): + return s + def _l2bytes(l): + return ''.join(map(chr, l)) +else: + # Python 3 + def _s2bytes(s): + return bytes(s, 'utf8') + def _l2bytes(l): + return bytes(l) # If you want feedparser to allow all URL schemes, set this to () # List culled from Python's urlparse documentation at: @@ -125,9 +132,10 @@ def _l2bytes(l): # https://secure.wikimedia.org/wikipedia/en/wiki/URI_scheme # Many more will likely need to be added! ACCEPTABLE_URI_SCHEMES = ( - 'file', 'ftp', 'gopher', 'h323', 'hdl', 'http', 'https', 'imap', 'mailto', - 'mms', 'news', 'nntp', 'prospero', 'rsync', 'rtsp', 'rtspu', 'sftp', - 'shttp', 'sip', 'sips', 'snews', 'svn', 'svn+ssh', 'telnet', 'wais', + 'file', 'ftp', 'gopher', 'h323', 'hdl', 'http', 'https', 'imap', 'magnet', + 'mailto', 'mms', 'news', 'nntp', 'prospero', 'rsync', 'rtsp', 'rtspu', + 'sftp', 'shttp', 'sip', 'sips', 'snews', 'svn', 'svn+ssh', 'telnet', + 'wais', # Additional common-but-unofficial schemes 'aim', 'callto', 'cvs', 'facetime', 'feed', 'git', 'gtalk', 'irc', 'ircs', 'irc6', 'itms', 'mms', 'msnim', 'skype', 'ssh', 'smb', 'svn', 'ymsg', @@ -135,13 +143,27 @@ ACCEPTABLE_URI_SCHEMES = ( #ACCEPTABLE_URI_SCHEMES = () # ---------- required modules (should come with any Python distribution) ---------- -import sgmllib, re, sys, copy, urlparse, time, types, cgi, urllib, urllib2, datetime +import cgi +import codecs +import copy +import datetime +import re +import struct +import time +import types +import urllib +import urllib2 +import urlparse +import warnings + +from htmlentitydefs import name2codepoint, codepoint2name, entitydefs + try: from io import BytesIO as _StringIO except ImportError: try: from cStringIO import StringIO as _StringIO - except: + except ImportError: from StringIO import StringIO as _StringIO # ---------- optional modules (feedparser will work without these, but with reduced functionality) ---------- @@ -149,23 +171,21 @@ except ImportError: # gzip is included with most Python distributions, but may not be available if you compiled your own try: import gzip -except: +except ImportError: gzip = None try: import zlib -except: +except ImportError: zlib = None # If a real XML parser is available, feedparser will attempt to use it. feedparser has -# been tested with the built-in SAX parser, PyXML, and libxml2. On platforms where the +# been tested with the built-in SAX parser and libxml2. On platforms where the # Python distribution does not come with an XML parser (such as Mac OS X 10.2 and some # versions of FreeBSD), feedparser will quietly fall back on regex-based parsing. try: import xml.sax - xml.sax.make_parser(PREFERRED_XML_PARSERS) # test for valid parsers from xml.sax.saxutils import escape as _xmlescape - _XML_AVAILABLE = 1 -except: +except ImportError: _XML_AVAILABLE = 0 def _xmlescape(data,entities={}): data = data.replace('&', '&') @@ -174,49 +194,96 @@ except: for char, entity in entities: data = data.replace(char, entity) return data +else: + try: + xml.sax.make_parser(PREFERRED_XML_PARSERS) # test for valid parsers + except xml.sax.SAXReaderNotAvailable: + _XML_AVAILABLE = 0 + else: + _XML_AVAILABLE = 1 -# cjkcodecs and iconv_codec provide support for more character encodings. -# Both are available from http://cjkpython.i18n.org/ +# sgmllib is not available by default in Python 3; if the end user doesn't have +# it available then we'll lose illformed XML parsing, content santizing, and +# microformat support (at least while feedparser depends on BeautifulSoup). try: - import cjkcodecs.aliases -except: - pass + import sgmllib +except ImportError: + # This is probably Python 3, which doesn't include sgmllib anymore + _SGML_AVAILABLE = 0 + + # Mock sgmllib enough to allow subclassing later on + class sgmllib(object): + class SGMLParser(object): + def goahead(self, i): + pass + def parse_starttag(self, i): + pass +else: + _SGML_AVAILABLE = 1 + + # sgmllib defines a number of module-level regular expressions that are + # insufficient for the XML parsing feedparser needs. Rather than modify + # the variables directly in sgmllib, they're defined here using the same + # names, and the compiled code objects of several sgmllib.SGMLParser + # methods are copied into _BaseHTMLProcessor so that they execute in + # feedparser's scope instead of sgmllib's scope. + charref = re.compile('&#(\d+|[xX][0-9a-fA-F]+);') + tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*') + attrfind = re.compile( + r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)[$]?(\s*=\s*' + r'(\'[^\']*\'|"[^"]*"|[][\-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?' + ) + + # Unfortunately, these must be copied over to prevent NameError exceptions + entityref = sgmllib.entityref + incomplete = sgmllib.incomplete + interesting = sgmllib.interesting + shorttag = sgmllib.shorttag + shorttagopen = sgmllib.shorttagopen + starttagopen = sgmllib.starttagopen + + class _EndBracketRegEx: + def __init__(self): + # Overriding the built-in sgmllib.endbracket regex allows the + # parser to find angle brackets embedded in element attributes. + self.endbracket = re.compile('''([^'"<>]|"[^"]*"(?=>|/|\s|\w+=)|'[^']*'(?=>|/|\s|\w+=))*(?=[<>])|.*?(?=[<>])''') + def search(self, target, index=0): + match = self.endbracket.match(target, index) + if match is not None: + # Returning a new object in the calling thread's context + # resolves a thread-safety. + return EndBracketMatch(match) + return None + class EndBracketMatch: + def __init__(self, match): + self.match = match + def start(self, n): + return self.match.end(n) + endbracket = _EndBracketRegEx() + + +# iconv_codec provides support for more character encodings. +# It's available from http://cjkpython.i18n.org/ try: import iconv_codec -except: +except ImportError: pass # chardet library auto-detects character encodings # Download from http://chardet.feedparser.org/ try: import chardet - if _debug: - import chardet.constants - chardet.constants._debug = 1 -except: +except ImportError: chardet = None -# reversable htmlentitydefs mappings for Python 2.2 -try: - from htmlentitydefs import name2codepoint, codepoint2name -except: - import htmlentitydefs - name2codepoint={} - codepoint2name={} - for (name,codepoint) in htmlentitydefs.entitydefs.iteritems(): - if codepoint.startswith('&#'): codepoint=unichr(int(codepoint[2:-1])) - name2codepoint[name]=ord(codepoint) - codepoint2name[ord(codepoint)]=name - -# BeautifulSoup parser used for parsing microformats from embedded HTML content +# BeautifulSoup is used to extract microformat content from HTML +# feedparser is tested using BeautifulSoup 3.2.0 # http://www.crummy.com/software/BeautifulSoup/ -# feedparser is tested with BeautifulSoup 3.0.x, but it might work with the -# older 2.x series. If it doesn't, and you can figure out why, I'll accept a -# patch and modify the compatibility statement accordingly. try: import BeautifulSoup -except: +except ImportError: BeautifulSoup = None + PARSE_MICROFORMATS = False # ---------- don't touch these ---------- class ThingsNobodyCaresAboutButMe(Exception): pass @@ -225,67 +292,32 @@ class CharacterEncodingUnknown(ThingsNobodyCaresAboutButMe): pass class NonXMLContentType(ThingsNobodyCaresAboutButMe): pass class UndeclaredNamespace(Exception): pass -sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*') -sgmllib.special = re.compile('<!') -sgmllib.charref = re.compile('&#(\d+|[xX][0-9a-fA-F]+);') - -if sgmllib.endbracket.search(' <').start(0): - class EndBracketRegEx: - def __init__(self): - # Overriding the built-in sgmllib.endbracket regex allows the - # parser to find angle brackets embedded in element attributes. - self.endbracket = re.compile('''([^'"<>]|"[^"]*"(?=>|/|\s|\w+=)|'[^']*'(?=>|/|\s|\w+=))*(?=[<>])|.*?(?=[<>])''') - def search(self,string,index=0): - match = self.endbracket.match(string,index) - if match is not None: - # Returning a new object in the calling thread's context - # resolves a thread-safety. - return EndBracketMatch(match) - return None - class EndBracketMatch: - def __init__(self, match): - self.match = match - def start(self, n): - return self.match.end(n) - sgmllib.endbracket = EndBracketRegEx() - -SUPPORTED_VERSIONS = {'': 'unknown', - 'rss090': 'RSS 0.90', - 'rss091n': 'RSS 0.91 (Netscape)', - 'rss091u': 'RSS 0.91 (Userland)', - 'rss092': 'RSS 0.92', - 'rss093': 'RSS 0.93', - 'rss094': 'RSS 0.94', - 'rss20': 'RSS 2.0', - 'rss10': 'RSS 1.0', - 'rss': 'RSS (unknown version)', - 'atom01': 'Atom 0.1', - 'atom02': 'Atom 0.2', - 'atom03': 'Atom 0.3', - 'atom10': 'Atom 1.0', - 'atom': 'Atom (unknown version)', - 'cdf': 'CDF', - 'hotrss': 'Hot RSS' +SUPPORTED_VERSIONS = {'': u'unknown', + 'rss090': u'RSS 0.90', + 'rss091n': u'RSS 0.91 (Netscape)', + 'rss091u': u'RSS 0.91 (Userland)', + 'rss092': u'RSS 0.92', + 'rss093': u'RSS 0.93', + 'rss094': u'RSS 0.94', + 'rss20': u'RSS 2.0', + 'rss10': u'RSS 1.0', + 'rss': u'RSS (unknown version)', + 'atom01': u'Atom 0.1', + 'atom02': u'Atom 0.2', + 'atom03': u'Atom 0.3', + 'atom10': u'Atom 1.0', + 'atom': u'Atom (unknown version)', + 'cdf': u'CDF', } -try: - UserDict = dict -except NameError: - # Python 2.1 does not have dict - from UserDict import UserDict - def dict(aList): - rc = {} - for k, v in aList: - rc[k] = v - return rc - -class FeedParserDict(UserDict): +class FeedParserDict(dict): keymap = {'channel': 'feed', 'items': 'entries', 'guid': 'id', 'date': 'updated', 'date_parsed': 'updated_parsed', 'description': ['summary', 'subtitle'], + 'description_detail': ['summary_detail', 'subtitle_detail'], 'url': ['href'], 'modified': 'updated', 'modified_parsed': 'updated_parsed', @@ -297,227 +329,220 @@ class FeedParserDict(UserDict): 'tagline_detail': 'subtitle_detail'} def __getitem__(self, key): if key == 'category': - return UserDict.__getitem__(self, 'tags')[0]['term'] - if key == 'enclosures': + try: + return dict.__getitem__(self, 'tags')[0]['term'] + except IndexError: + raise KeyError, "object doesn't have key 'category'" + elif key == 'enclosures': norel = lambda link: FeedParserDict([(name,value) for (name,value) in link.items() if name!='rel']) - return [norel(link) for link in UserDict.__getitem__(self, 'links') if link['rel']=='enclosure'] - if key == 'license': - for link in UserDict.__getitem__(self, 'links'): - if link['rel']=='license' and link.has_key('href'): + return [norel(link) for link in dict.__getitem__(self, 'links') if link['rel']==u'enclosure'] + elif key == 'license': + for link in dict.__getitem__(self, 'links'): + if link['rel']==u'license' and 'href' in link: return link['href'] - if key == 'categories': - return [(tag['scheme'], tag['term']) for tag in UserDict.__getitem__(self, 'tags')] - realkey = self.keymap.get(key, key) - if type(realkey) == types.ListType: - for k in realkey: - if UserDict.__contains__(self, k): - return UserDict.__getitem__(self, k) - if UserDict.__contains__(self, key): - return UserDict.__getitem__(self, key) - return UserDict.__getitem__(self, realkey) + elif key == 'updated': + # Temporarily help developers out by keeping the old + # broken behavior that was reported in issue 310. + # This fix was proposed in issue 328. + if not dict.__contains__(self, 'updated') and \ + dict.__contains__(self, 'published'): + warnings.warn("To avoid breaking existing software while " + "fixing issue 310, a temporary mapping has been created " + "from `updated` to `published` if `updated` doesn't " + "exist. This fallback will be removed in a future version " + "of feedparser.", DeprecationWarning) + return dict.__getitem__(self, 'published') + return dict.__getitem__(self, 'updated') + elif key == 'updated_parsed': + if not dict.__contains__(self, 'updated_parsed') and \ + dict.__contains__(self, 'published_parsed'): + warnings.warn("To avoid breaking existing software while " + "fixing issue 310, a temporary mapping has been created " + "from `updated_parsed` to `published_parsed` if " + "`updated_parsed` doesn't exist. This fallback will be " + "removed in a future version of feedparser.", + DeprecationWarning) + return dict.__getitem__(self, 'published_parsed') + return dict.__getitem__(self, 'updated_parsed') + else: + realkey = self.keymap.get(key, key) + if isinstance(realkey, list): + for k in realkey: + if dict.__contains__(self, k): + return dict.__getitem__(self, k) + elif dict.__contains__(self, realkey): + return dict.__getitem__(self, realkey) + return dict.__getitem__(self, key) - def __setitem__(self, key, value): - for k in self.keymap.keys(): - if key == k: - key = self.keymap[k] - if type(key) == types.ListType: - key = key[0] - return UserDict.__setitem__(self, key, value) + def __contains__(self, key): + if key in ('updated', 'updated_parsed'): + # Temporarily help developers out by keeping the old + # broken behavior that was reported in issue 310. + # This fix was proposed in issue 328. + return dict.__contains__(self, key) + try: + self.__getitem__(key) + except KeyError: + return False + else: + return True + + has_key = __contains__ def get(self, key, default=None): - if self.has_key(key): - return self[key] - else: + try: + return self.__getitem__(key) + except KeyError: return default + def __setitem__(self, key, value): + key = self.keymap.get(key, key) + if isinstance(key, list): + key = key[0] + return dict.__setitem__(self, key, value) + def setdefault(self, key, value): - if not self.has_key(key): + if key not in self: self[key] = value + return value return self[key] - - def has_key(self, key): - try: - return hasattr(self, key) or UserDict.__contains__(self, key) - except AttributeError: - return False - # This alias prevents the 2to3 tool from changing the semantics of the - # __contains__ function below and exhausting the maximum recursion depth - __has_key = has_key - + def __getattr__(self, key): + # __getattribute__() is called first; this will be called + # only if an attribute was not already found try: - return self.__dict__[key] - except KeyError: - pass - try: - assert not key.startswith('_') return self.__getitem__(key) - except: + except KeyError: raise AttributeError, "object has no attribute '%s'" % key - def __setattr__(self, key, value): - if key.startswith('_') or key == 'data': - self.__dict__[key] = value - else: - return self.__setitem__(key, value) + def __hash__(self): + return id(self) - def __contains__(self, key): - return self.__has_key(key) - -def zopeCompatibilityHack(): - global FeedParserDict - del FeedParserDict - def FeedParserDict(aDict=None): - rc = {} - if aDict: - rc.update(aDict) - return rc - -_ebcdic_to_ascii_map = None -def _ebcdic_to_ascii(s): - global _ebcdic_to_ascii_map - if not _ebcdic_to_ascii_map: - emap = ( - 0,1,2,3,156,9,134,127,151,141,142,11,12,13,14,15, - 16,17,18,19,157,133,8,135,24,25,146,143,28,29,30,31, - 128,129,130,131,132,10,23,27,136,137,138,139,140,5,6,7, - 144,145,22,147,148,149,150,4,152,153,154,155,20,21,158,26, - 32,160,161,162,163,164,165,166,167,168,91,46,60,40,43,33, - 38,169,170,171,172,173,174,175,176,177,93,36,42,41,59,94, - 45,47,178,179,180,181,182,183,184,185,124,44,37,95,62,63, - 186,187,188,189,190,191,192,193,194,96,58,35,64,39,61,34, - 195,97,98,99,100,101,102,103,104,105,196,197,198,199,200,201, - 202,106,107,108,109,110,111,112,113,114,203,204,205,206,207,208, - 209,126,115,116,117,118,119,120,121,122,210,211,212,213,214,215, - 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231, - 123,65,66,67,68,69,70,71,72,73,232,233,234,235,236,237, - 125,74,75,76,77,78,79,80,81,82,238,239,240,241,242,243, - 92,159,83,84,85,86,87,88,89,90,244,245,246,247,248,249, - 48,49,50,51,52,53,54,55,56,57,250,251,252,253,254,255 - ) - _ebcdic_to_ascii_map = _maketrans( \ - _l2bytes(range(256)), _l2bytes(emap)) - return s.translate(_ebcdic_to_ascii_map) - _cp1252 = { - unichr(128): unichr(8364), # euro sign - unichr(130): unichr(8218), # single low-9 quotation mark - unichr(131): unichr( 402), # latin small letter f with hook - unichr(132): unichr(8222), # double low-9 quotation mark - unichr(133): unichr(8230), # horizontal ellipsis - unichr(134): unichr(8224), # dagger - unichr(135): unichr(8225), # double dagger - unichr(136): unichr( 710), # modifier letter circumflex accent - unichr(137): unichr(8240), # per mille sign - unichr(138): unichr( 352), # latin capital letter s with caron - unichr(139): unichr(8249), # single left-pointing angle quotation mark - unichr(140): unichr( 338), # latin capital ligature oe - unichr(142): unichr( 381), # latin capital letter z with caron - unichr(145): unichr(8216), # left single quotation mark - unichr(146): unichr(8217), # right single quotation mark - unichr(147): unichr(8220), # left double quotation mark - unichr(148): unichr(8221), # right double quotation mark - unichr(149): unichr(8226), # bullet - unichr(150): unichr(8211), # en dash - unichr(151): unichr(8212), # em dash - unichr(152): unichr( 732), # small tilde - unichr(153): unichr(8482), # trade mark sign - unichr(154): unichr( 353), # latin small letter s with caron - unichr(155): unichr(8250), # single right-pointing angle quotation mark - unichr(156): unichr( 339), # latin small ligature oe - unichr(158): unichr( 382), # latin small letter z with caron - unichr(159): unichr( 376)} # latin capital letter y with diaeresis + 128: unichr(8364), # euro sign + 130: unichr(8218), # single low-9 quotation mark + 131: unichr( 402), # latin small letter f with hook + 132: unichr(8222), # double low-9 quotation mark + 133: unichr(8230), # horizontal ellipsis + 134: unichr(8224), # dagger + 135: unichr(8225), # double dagger + 136: unichr( 710), # modifier letter circumflex accent + 137: unichr(8240), # per mille sign + 138: unichr( 352), # latin capital letter s with caron + 139: unichr(8249), # single left-pointing angle quotation mark + 140: unichr( 338), # latin capital ligature oe + 142: unichr( 381), # latin capital letter z with caron + 145: unichr(8216), # left single quotation mark + 146: unichr(8217), # right single quotation mark + 147: unichr(8220), # left double quotation mark + 148: unichr(8221), # right double quotation mark + 149: unichr(8226), # bullet + 150: unichr(8211), # en dash + 151: unichr(8212), # em dash + 152: unichr( 732), # small tilde + 153: unichr(8482), # trade mark sign + 154: unichr( 353), # latin small letter s with caron + 155: unichr(8250), # single right-pointing angle quotation mark + 156: unichr( 339), # latin small ligature oe + 158: unichr( 382), # latin small letter z with caron + 159: unichr( 376), # latin capital letter y with diaeresis +} _urifixer = re.compile('^([A-Za-z][A-Za-z0-9+-.]*://)(/*)(.*?)') def _urljoin(base, uri): uri = _urifixer.sub(r'\1\3', uri) - try: - return urlparse.urljoin(base, uri) - except: - uri = urlparse.urlunparse([urllib.quote(part) for part in urlparse.urlparse(uri)]) - return urlparse.urljoin(base, uri) + #try: + if not isinstance(uri, unicode): + uri = uri.decode('utf-8', 'ignore') + uri = urlparse.urljoin(base, uri) + if not isinstance(uri, unicode): + return uri.decode('utf-8', 'ignore') + return uri + #except: + # uri = urlparse.urlunparse([urllib.quote(part) for part in urlparse.urlparse(uri)]) + # return urlparse.urljoin(base, uri) class _FeedParserMixin: - namespaces = {'': '', - 'http://backend.userland.com/rss': '', - 'http://blogs.law.harvard.edu/tech/rss': '', - 'http://purl.org/rss/1.0/': '', - 'http://my.netscape.com/rdf/simple/0.9/': '', - 'http://example.com/newformat#': '', - 'http://example.com/necho': '', - 'http://purl.org/echo/': '', - 'uri/of/echo/namespace#': '', - 'http://purl.org/pie/': '', - 'http://purl.org/atom/ns#': '', - 'http://www.w3.org/2005/Atom': '', - 'http://purl.org/rss/1.0/modules/rss091#': '', - - 'http://webns.net/mvcb/': 'admin', - 'http://purl.org/rss/1.0/modules/aggregation/': 'ag', - 'http://purl.org/rss/1.0/modules/annotate/': 'annotate', - 'http://media.tangent.org/rss/1.0/': 'audio', - 'http://backend.userland.com/blogChannelModule': 'blogChannel', - 'http://web.resource.org/cc/': 'cc', - 'http://backend.userland.com/creativeCommonsRssModule': 'creativeCommons', - 'http://purl.org/rss/1.0/modules/company': 'co', - 'http://purl.org/rss/1.0/modules/content/': 'content', - 'http://my.theinfo.org/changed/1.0/rss/': 'cp', - 'http://purl.org/dc/elements/1.1/': 'dc', - 'http://purl.org/dc/terms/': 'dcterms', - 'http://purl.org/rss/1.0/modules/email/': 'email', - 'http://purl.org/rss/1.0/modules/event/': 'ev', - 'http://rssnamespace.org/feedburner/ext/1.0': 'feedburner', - 'http://freshmeat.net/rss/fm/': 'fm', - 'http://xmlns.com/foaf/0.1/': 'foaf', - 'http://www.w3.org/2003/01/geo/wgs84_pos#': 'geo', - 'http://postneo.com/icbm/': 'icbm', - 'http://purl.org/rss/1.0/modules/image/': 'image', - 'http://www.itunes.com/DTDs/PodCast-1.0.dtd': 'itunes', - 'http://example.com/DTDs/PodCast-1.0.dtd': 'itunes', - 'http://purl.org/rss/1.0/modules/link/': 'l', - 'http://search.yahoo.com/mrss': 'media', - #Version 1.1.2 of the Media RSS spec added the trailing slash on the namespace - 'http://search.yahoo.com/mrss/': 'media', - 'http://madskills.com/public/xml/rss/module/pingback/': 'pingback', - 'http://prismstandard.org/namespaces/1.2/basic/': 'prism', - 'http://www.w3.org/1999/02/22-rdf-syntax-ns#': 'rdf', - 'http://www.w3.org/2000/01/rdf-schema#': 'rdfs', - 'http://purl.org/rss/1.0/modules/reference/': 'ref', - 'http://purl.org/rss/1.0/modules/richequiv/': 'reqv', - 'http://purl.org/rss/1.0/modules/search/': 'search', - 'http://purl.org/rss/1.0/modules/slash/': 'slash', - 'http://schemas.xmlsoap.org/soap/envelope/': 'soap', - 'http://purl.org/rss/1.0/modules/servicestatus/': 'ss', - 'http://hacks.benhammersley.com/rss/streaming/': 'str', - 'http://purl.org/rss/1.0/modules/subscription/': 'sub', - 'http://purl.org/rss/1.0/modules/syndication/': 'sy', - 'http://schemas.pocketsoap.com/rss/myDescModule/': 'szf', - 'http://purl.org/rss/1.0/modules/taxonomy/': 'taxo', - 'http://purl.org/rss/1.0/modules/threading/': 'thr', - 'http://purl.org/rss/1.0/modules/textinput/': 'ti', - 'http://madskills.com/public/xml/rss/module/trackback/':'trackback', - 'http://wellformedweb.org/commentAPI/': 'wfw', - 'http://purl.org/rss/1.0/modules/wiki/': 'wiki', - 'http://www.w3.org/1999/xhtml': 'xhtml', - 'http://www.w3.org/1999/xlink': 'xlink', - 'http://www.w3.org/XML/1998/namespace': 'xml' -} + namespaces = { + '': '', + 'http://backend.userland.com/rss': '', + 'http://blogs.law.harvard.edu/tech/rss': '', + 'http://purl.org/rss/1.0/': '', + 'http://my.netscape.com/rdf/simple/0.9/': '', + 'http://example.com/newformat#': '', + 'http://example.com/necho': '', + 'http://purl.org/echo/': '', + 'uri/of/echo/namespace#': '', + 'http://purl.org/pie/': '', + 'http://purl.org/atom/ns#': '', + 'http://www.w3.org/2005/Atom': '', + 'http://purl.org/rss/1.0/modules/rss091#': '', + + 'http://webns.net/mvcb/': 'admin', + 'http://purl.org/rss/1.0/modules/aggregation/': 'ag', + 'http://purl.org/rss/1.0/modules/annotate/': 'annotate', + 'http://media.tangent.org/rss/1.0/': 'audio', + 'http://backend.userland.com/blogChannelModule': 'blogChannel', + 'http://web.resource.org/cc/': 'cc', + 'http://backend.userland.com/creativeCommonsRssModule': 'creativeCommons', + 'http://purl.org/rss/1.0/modules/company': 'co', + 'http://purl.org/rss/1.0/modules/content/': 'content', + 'http://my.theinfo.org/changed/1.0/rss/': 'cp', + 'http://purl.org/dc/elements/1.1/': 'dc', + 'http://purl.org/dc/terms/': 'dcterms', + 'http://purl.org/rss/1.0/modules/email/': 'email', + 'http://purl.org/rss/1.0/modules/event/': 'ev', + 'http://rssnamespace.org/feedburner/ext/1.0': 'feedburner', + 'http://freshmeat.net/rss/fm/': 'fm', + 'http://xmlns.com/foaf/0.1/': 'foaf', + 'http://www.w3.org/2003/01/geo/wgs84_pos#': 'geo', + 'http://postneo.com/icbm/': 'icbm', + 'http://purl.org/rss/1.0/modules/image/': 'image', + 'http://www.itunes.com/DTDs/PodCast-1.0.dtd': 'itunes', + 'http://example.com/DTDs/PodCast-1.0.dtd': 'itunes', + 'http://purl.org/rss/1.0/modules/link/': 'l', + 'http://search.yahoo.com/mrss': 'media', + # Version 1.1.2 of the Media RSS spec added the trailing slash on the namespace + 'http://search.yahoo.com/mrss/': 'media', + 'http://madskills.com/public/xml/rss/module/pingback/': 'pingback', + 'http://prismstandard.org/namespaces/1.2/basic/': 'prism', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#': 'rdf', + 'http://www.w3.org/2000/01/rdf-schema#': 'rdfs', + 'http://purl.org/rss/1.0/modules/reference/': 'ref', + 'http://purl.org/rss/1.0/modules/richequiv/': 'reqv', + 'http://purl.org/rss/1.0/modules/search/': 'search', + 'http://purl.org/rss/1.0/modules/slash/': 'slash', + 'http://schemas.xmlsoap.org/soap/envelope/': 'soap', + 'http://purl.org/rss/1.0/modules/servicestatus/': 'ss', + 'http://hacks.benhammersley.com/rss/streaming/': 'str', + 'http://purl.org/rss/1.0/modules/subscription/': 'sub', + 'http://purl.org/rss/1.0/modules/syndication/': 'sy', + 'http://schemas.pocketsoap.com/rss/myDescModule/': 'szf', + 'http://purl.org/rss/1.0/modules/taxonomy/': 'taxo', + 'http://purl.org/rss/1.0/modules/threading/': 'thr', + 'http://purl.org/rss/1.0/modules/textinput/': 'ti', + 'http://madskills.com/public/xml/rss/module/trackback/': 'trackback', + 'http://wellformedweb.org/commentAPI/': 'wfw', + 'http://purl.org/rss/1.0/modules/wiki/': 'wiki', + 'http://www.w3.org/1999/xhtml': 'xhtml', + 'http://www.w3.org/1999/xlink': 'xlink', + 'http://www.w3.org/XML/1998/namespace': 'xml', + } _matchnamespaces = {} - can_be_relative_uri = ['link', 'id', 'wfw_comment', 'wfw_commentrss', 'docs', 'url', 'href', 'comments', 'icon', 'logo'] - can_contain_relative_uris = ['content', 'title', 'summary', 'info', 'tagline', 'subtitle', 'copyright', 'rights', 'description'] - can_contain_dangerous_markup = ['content', 'title', 'summary', 'info', 'tagline', 'subtitle', 'copyright', 'rights', 'description'] - html_types = ['text/html', 'application/xhtml+xml'] - - def __init__(self, baseuri=None, baselang=None, encoding='utf-8'): - if _debug: sys.stderr.write('initializing FeedParser\n') + can_be_relative_uri = set(['link', 'id', 'wfw_comment', 'wfw_commentrss', 'docs', 'url', 'href', 'comments', 'icon', 'logo']) + can_contain_relative_uris = set(['content', 'title', 'summary', 'info', 'tagline', 'subtitle', 'copyright', 'rights', 'description']) + can_contain_dangerous_markup = set(['content', 'title', 'summary', 'info', 'tagline', 'subtitle', 'copyright', 'rights', 'description']) + html_types = [u'text/html', u'application/xhtml+xml'] + + def __init__(self, baseuri=None, baselang=None, encoding=u'utf-8'): if not self._matchnamespaces: for k, v in self.namespaces.items(): self._matchnamespaces[k.lower()] = v self.feeddata = FeedParserDict() # feed-level data self.encoding = encoding # character encoding self.entries = [] # list of entry-level data - self.version = '' # feed type/version, see SUPPORTED_VERSIONS + self.version = u'' # feed type/version, see SUPPORTED_VERSIONS self.namespacesInUse = {} # dictionary of namespaces defined by the feed # the following are used internally to track state; @@ -538,31 +563,47 @@ class _FeedParserMixin: self.elementstack = [] self.basestack = [] self.langstack = [] - self.baseuri = baseuri or '' + self.baseuri = baseuri or u'' self.lang = baselang or None self.svgOK = 0 - self.hasTitle = 0 + self.title_depth = -1 + self.depth = 0 if baselang: self.feeddata['language'] = baselang.replace('_','-') - def unknown_starttag(self, tag, attrs): - if _debug: sys.stderr.write('start %s with %s\n' % (tag, attrs)) - # normalize attrs - attrs = [(k.lower(), v) for k, v in attrs] - attrs = [(k, k in ('rel', 'type') and v.lower() or v) for k, v in attrs] - # the sgml parser doesn't handle entities in attributes, but + # A map of the following form: + # { + # object_that_value_is_set_on: { + # property_name: depth_of_node_property_was_extracted_from, + # other_property: depth_of_node_property_was_extracted_from, + # }, + # } + self.property_depth_map = {} + + def _normalize_attributes(self, kv): + k = kv[0].lower() + v = k in ('rel', 'type') and kv[1].lower() or kv[1] + # the sgml parser doesn't handle entities in attributes, nor + # does it pass the attribute values through as unicode, while # strict xml parsers do -- account for this difference if isinstance(self, _LooseFeedParser): - attrs = [(k, v.replace('&', '&')) for k, v in attrs] - + v = v.replace('&', '&') + if not isinstance(v, unicode): + v = v.decode('utf-8') + return (k, v) + + def unknown_starttag(self, tag, attrs): + # increment depth counter + self.depth += 1 + + # normalize attrs + attrs = map(self._normalize_attributes, attrs) + # track xml:base and xml:lang attrsD = dict(attrs) baseuri = attrsD.get('xml:base', attrsD.get('base')) or self.baseuri - if type(baseuri) != type(u''): - try: - baseuri = unicode(baseuri, self.encoding) - except: - baseuri = unicode(baseuri, 'iso-8859-1') + if not isinstance(baseuri, unicode): + baseuri = baseuri.decode(self.encoding, 'ignore') # ensure that self.baseuri is always an absolute URI that # uses a whitelisted URI scheme (e.g. not `javscript:`) if self.baseuri: @@ -582,7 +623,7 @@ class _FeedParserMixin: self.lang = lang self.basestack.append(self.baseuri) self.langstack.append(lang) - + # track namespaces for prefix, uri in attrs: if prefix.startswith('xmlns:'): @@ -591,11 +632,12 @@ class _FeedParserMixin: self.trackNamespace(None, uri) # track inline content - if self.incontent and self.contentparams.has_key('type') and not self.contentparams.get('type', 'xml').endswith('xml'): - if tag in ['xhtml:div', 'div']: return # typepad does this 10/2007 + if self.incontent and not self.contentparams.get('type', u'xml').endswith(u'xml'): + if tag in ('xhtml:div', 'div'): + return # typepad does this 10/2007 # element declared itself as escaped markup, but it isn't really - self.contentparams['type'] = 'application/xhtml+xml' - if self.incontent and self.contentparams.get('type') == 'application/xhtml+xml': + self.contentparams['type'] = u'application/xhtml+xml' + if self.incontent and self.contentparams.get('type') == u'application/xhtml+xml': if tag.find(':') <> -1: prefix, tag = tag.split(':', 1) namespace = self.namespacesInUse.get(prefix, '') @@ -603,7 +645,8 @@ class _FeedParserMixin: attrs.append(('xmlns',namespace)) if tag=='svg' and namespace=='http://www.w3.org/2000/svg': attrs.append(('xmlns',namespace)) - if tag == 'svg': self.svgOK += 1 + if tag == 'svg': + self.svgOK += 1 return self.handle_data('<%s%s>' % (tag, self.strattrs(attrs)), escape=0) # match namespaces @@ -620,7 +663,7 @@ class _FeedParserMixin: self.intextinput = 0 if (not prefix) and tag not in ('title', 'link', 'description', 'url', 'href', 'width', 'height'): self.inimage = 0 - + # call special handler (if defined) or default handler methodname = '_start_' + prefix + suffix try: @@ -638,7 +681,6 @@ class _FeedParserMixin: context[unknown_tag] = attrsD def unknown_endtag(self, tag): - if _debug: sys.stderr.write('end %s\n' % tag) # match namespaces if tag.find(':') <> -1: prefix, suffix = tag.split(':', 1) @@ -647,23 +689,26 @@ class _FeedParserMixin: prefix = self.namespacemap.get(prefix, prefix) if prefix: prefix = prefix + '_' - if suffix == 'svg' and self.svgOK: self.svgOK -= 1 + if suffix == 'svg' and self.svgOK: + self.svgOK -= 1 # call special handler (if defined) or default handler methodname = '_end_' + prefix + suffix try: - if self.svgOK: raise AttributeError() + if self.svgOK: + raise AttributeError() method = getattr(self, methodname) method() except AttributeError: self.pop(prefix + suffix) # track inline content - if self.incontent and self.contentparams.has_key('type') and not self.contentparams.get('type', 'xml').endswith('xml'): + if self.incontent and not self.contentparams.get('type', u'xml').endswith(u'xml'): # element declared itself as escaped markup, but it isn't really - if tag in ['xhtml:div', 'div']: return # typepad does this 10/2007 - self.contentparams['type'] = 'application/xhtml+xml' - if self.incontent and self.contentparams.get('type') == 'application/xhtml+xml': + if tag in ('xhtml:div', 'div'): + return # typepad does this 10/2007 + self.contentparams['type'] = u'application/xhtml+xml' + if self.incontent and self.contentparams.get('type') == u'application/xhtml+xml': tag = tag.split(':')[-1] self.handle_data('</%s>' % tag, escape=0) @@ -677,9 +722,12 @@ class _FeedParserMixin: if self.langstack: # and (self.langstack[-1] is not None): self.lang = self.langstack[-1] + self.depth -= 1 + def handle_charref(self, ref): # called for each character reference, e.g. for ' ', ref will be '160' - if not self.elementstack: return + if not self.elementstack: + return ref = ref.lower() if ref in ('34', '38', '39', '60', '62', 'x22', 'x26', 'x27', 'x3c', 'x3e'): text = '&#%s;' % ref @@ -693,25 +741,29 @@ class _FeedParserMixin: def handle_entityref(self, ref): # called for each entity reference, e.g. for '©', ref will be 'copy' - if not self.elementstack: return - if _debug: sys.stderr.write('entering handle_entityref with %s\n' % ref) + if not self.elementstack: + return if ref in ('lt', 'gt', 'quot', 'amp', 'apos'): text = '&%s;' % ref - elif ref in self.entities.keys(): + elif ref in self.entities: text = self.entities[ref] if text.startswith('&#') and text.endswith(';'): return self.handle_entityref(text) else: - try: name2codepoint[ref] - except KeyError: text = '&%s;' % ref - else: text = unichr(name2codepoint[ref]).encode('utf-8') + try: + name2codepoint[ref] + except KeyError: + text = '&%s;' % ref + else: + text = unichr(name2codepoint[ref]).encode('utf-8') self.elementstack[-1][2].append(text) def handle_data(self, text, escape=1): # called for each block of plain text, i.e. outside of any tag and # not containing any character or entity references - if not self.elementstack: return - if escape and self.contentparams.get('type') == 'application/xhtml+xml': + if not self.elementstack: + return + if escape and self.contentparams.get('type') == u'application/xhtml+xml': text = _xmlescape(text) self.elementstack[-1][2].append(text) @@ -728,7 +780,6 @@ class _FeedParserMixin: def parse_declaration(self, i): # override internal declaration handler to handle CDATA blocks - if _debug: sys.stderr.write('entering parse_declaration\n') if self.rawdata[i:i+9] == '<![CDATA[': k = self.rawdata.find(']]>', i) if k == -1: @@ -747,35 +798,36 @@ class _FeedParserMixin: def mapContentType(self, contentType): contentType = contentType.lower() - if contentType == 'text': - contentType = 'text/plain' + if contentType == 'text' or contentType == 'plain': + contentType = u'text/plain' elif contentType == 'html': - contentType = 'text/html' + contentType = u'text/html' elif contentType == 'xhtml': - contentType = 'application/xhtml+xml' + contentType = u'application/xhtml+xml' return contentType - + def trackNamespace(self, prefix, uri): loweruri = uri.lower() - if (prefix, loweruri) == (None, 'http://my.netscape.com/rdf/simple/0.9/') and not self.version: - self.version = 'rss090' - if loweruri == 'http://purl.org/rss/1.0/' and not self.version: - self.version = 'rss10' - if loweruri == 'http://www.w3.org/2005/atom' and not self.version: - self.version = 'atom10' - if loweruri.find('backend.userland.com/rss') <> -1: + if not self.version: + if (prefix, loweruri) == (None, 'http://my.netscape.com/rdf/simple/0.9/'): + self.version = u'rss090' + elif loweruri == 'http://purl.org/rss/1.0/': + self.version = u'rss10' + elif loweruri == 'http://www.w3.org/2005/atom': + self.version = u'atom10' + if loweruri.find(u'backend.userland.com/rss') <> -1: # match any backend.userland.com namespace - uri = 'http://backend.userland.com/rss' + uri = u'http://backend.userland.com/rss' loweruri = uri - if self._matchnamespaces.has_key(loweruri): + if loweruri in self._matchnamespaces: self.namespacemap[prefix] = self._matchnamespaces[loweruri] self.namespacesInUse[self._matchnamespaces[loweruri]] = uri else: self.namespacesInUse[prefix or ''] = uri def resolveURI(self, uri): - return _urljoin(self.baseuri or '', uri) - + return _urljoin(self.baseuri or u'', uri) + def decodeEntities(self, element, data): return data @@ -786,12 +838,14 @@ class _FeedParserMixin: self.elementstack.append([element, expectingText, []]) def pop(self, element, stripWhitespace=1): - if not self.elementstack: return - if self.elementstack[-1][0] != element: return - + if not self.elementstack: + return + if self.elementstack[-1][0] != element: + return + element, expectingText, pieces = self.elementstack.pop() - if self.version == 'atom10' and self.contentparams.get('type','text') == 'application/xhtml+xml': + if self.version == u'atom10' and self.contentparams.get('type', u'text') == u'application/xhtml+xml': # remove enclosing child element, but only if it is a <div> and # only if all the remaining content is nested underneath it. # This means that the divs would be retained in the following: @@ -805,7 +859,8 @@ class _FeedParserMixin: for piece in pieces[:-1]: if piece.startswith('</'): depth -= 1 - if depth == 0: break + if depth == 0: + break elif piece.startswith('<') and not piece.endswith('/>'): depth += 1 else: @@ -813,13 +868,14 @@ class _FeedParserMixin: # Ensure each piece is a str for Python 3 for (i, v) in enumerate(pieces): - if not isinstance(v, basestring): + if not isinstance(v, unicode): pieces[i] = v.decode('utf-8') - output = ''.join(pieces) + output = u''.join(pieces) if stripWhitespace: output = output.strip() - if not expectingText: return output + if not expectingText: + return output # decode base64 content if base64 and self.contentparams.get('base64', 0): @@ -833,17 +889,20 @@ class _FeedParserMixin: # In Python 3, base64 takes and outputs bytes, not str # This may not be the most correct way to accomplish this output = _base64decode(output.encode('utf-8')).decode('utf-8') - + # resolve relative URIs if (element in self.can_be_relative_uri) and output: output = self.resolveURI(output) - + # decode entities within embedded markup if not self.contentparams.get('base64', 0): output = self.decodeEntities(element, output) - if self.lookslikehtml(output): - self.contentparams['type']='text/html' + # some feed formats require consumers to guess + # whether the content is html or plain text + if not self.version.startswith(u'atom') and self.contentparams.get('type') == u'text/plain': + if self.lookslikehtml(output): + self.contentparams['type'] = u'text/html' # remove temporary cruft from contentparams try: @@ -855,16 +914,16 @@ class _FeedParserMixin: except KeyError: pass - is_htmlish = self.mapContentType(self.contentparams.get('type', 'text/html')) in self.html_types + is_htmlish = self.mapContentType(self.contentparams.get('type', u'text/html')) in self.html_types # resolve relative URIs within embedded markup if is_htmlish and RESOLVE_RELATIVE_URIS: if element in self.can_contain_relative_uris: - output = _resolveRelativeURIs(output, self.baseuri, self.encoding, self.contentparams.get('type', 'text/html')) - + output = _resolveRelativeURIs(output, self.baseuri, self.encoding, self.contentparams.get('type', u'text/html')) + # parse microformats # (must do this before sanitizing because some microformats # rely on elements that we sanitize) - if is_htmlish and element in ['content', 'description', 'summary']: + if PARSE_MICROFORMATS and is_htmlish and element in ['content', 'description', 'summary']: mfresults = _parseMicroformats(output, self.baseuri, self.encoding) if mfresults: for tag in mfresults.get('tags', []): @@ -876,37 +935,34 @@ class _FeedParserMixin: vcard = mfresults.get('vcard') if vcard: self._getContext()['vcard'] = vcard - + # sanitize embedded markup if is_htmlish and SANITIZE_HTML: if element in self.can_contain_dangerous_markup: - output = _sanitizeHTML(output, self.encoding, self.contentparams.get('type', 'text/html')) + output = _sanitizeHTML(output, self.encoding, self.contentparams.get('type', u'text/html')) - if self.encoding and type(output) != type(u''): - try: - output = unicode(output, self.encoding) - except: - pass + if self.encoding and not isinstance(output, unicode): + output = output.decode(self.encoding, 'ignore') # address common error where people take data that is already # utf-8, presume that it is iso-8859-1, and re-encode it. - if self.encoding in ('utf-8', 'utf-8_INVALID_PYTHON_3') and type(output) == type(u''): + if self.encoding in (u'utf-8', u'utf-8_INVALID_PYTHON_3') and isinstance(output, unicode): try: - output = unicode(output.encode('iso-8859-1'), 'utf-8') - except: + output = output.encode('iso-8859-1').decode('utf-8') + except (UnicodeEncodeError, UnicodeDecodeError): pass # map win-1252 extensions to the proper code points - if type(output) == type(u''): - output = u''.join([c in _cp1252.keys() and _cp1252[c] or c for c in output]) + if isinstance(output, unicode): + output = output.translate(_cp1252) # categories/tags/keywords/whatever are handled in _end_category if element == 'category': return output - if element == 'title' and self.hasTitle: + if element == 'title' and -1 < self.title_depth <= self.depth: return output - + # store output in appropriate place(s) if self.inentry and not self.insource: if element == 'content': @@ -926,7 +982,10 @@ class _FeedParserMixin: else: if element == 'description': element = 'summary' - self.entries[-1][element] = output + old_value_depth = self.property_depth_map.setdefault(self.entries[-1], {}).get(element) + if old_value_depth is None or self.depth <= old_value_depth: + self.property_depth_map[self.entries[-1]][element] = self.depth + self.entries[-1][element] = output if self.incontent: contentparams = copy.deepcopy(self.contentparams) contentparams['value'] = output @@ -949,7 +1008,8 @@ class _FeedParserMixin: def pushContent(self, tag, attrsD, defaultContentType, expectingText): self.incontent += 1 - if self.lang: self.lang=self.lang.replace('_','-') + if self.lang: + self.lang=self.lang.replace('_','-') self.contentparams = FeedParserDict({ 'type': self.mapContentType(attrsD.get('type', defaultContentType)), 'language': self.lang, @@ -962,26 +1022,25 @@ class _FeedParserMixin: self.incontent -= 1 self.contentparams.clear() return value - + # a number of elements in a number of RSS variants are nominally plain # text, but this is routinely ignored. This is an attempt to detect # the most common cases. As false positives often result in silent # data loss, this function errs on the conservative side. - def lookslikehtml(self, s): - if self.version.startswith('atom'): return - if self.contentparams.get('type','text/html') != 'text/plain': return - - # must have a close tag or a entity reference to qualify - if not (re.search(r'</(\w+)>',s) or re.search("&#?\w+;",s)): return + @staticmethod + def lookslikehtml(s): + # must have a close tag or an entity reference to qualify + if not (re.search(r'</(\w+)>',s) or re.search("&#?\w+;",s)): + return # all tags must be in a restricted subset of valid HTML tags if filter(lambda t: t.lower() not in _HTMLSanitizer.acceptable_elements, - re.findall(r'</?(\w+)',s)): return + re.findall(r'</?(\w+)',s)): + return # all entities must have been defined as valid HTML entities - from htmlentitydefs import entitydefs - if filter(lambda e: e not in entitydefs.keys(), - re.findall(r'&(\w+);',s)): return + if filter(lambda e: e not in entitydefs.keys(), re.findall(r'&(\w+);', s)): + return return 1 @@ -993,18 +1052,18 @@ class _FeedParserMixin: prefix = self.namespacemap.get(prefix, prefix) name = prefix + ':' + suffix return name - + def _getAttribute(self, attrsD, name): return attrsD.get(self._mapToStandardPrefix(name)) def _isBase64(self, attrsD, contentparams): if attrsD.get('mode', '') == 'base64': return 1 - if self.contentparams['type'].startswith('text/'): + if self.contentparams['type'].startswith(u'text/'): return 0 - if self.contentparams['type'].endswith('+xml'): + if self.contentparams['type'].endswith(u'+xml'): return 0 - if self.contentparams['type'].endswith('/xml'): + if self.contentparams['type'].endswith(u'/xml'): return 0 return 1 @@ -1021,7 +1080,7 @@ class _FeedParserMixin: pass attrsD['href'] = href return attrsD - + def _save(self, key, value, overwrite=False): context = self._getContext() if overwrite: @@ -1030,66 +1089,62 @@ class _FeedParserMixin: context.setdefault(key, value) def _start_rss(self, attrsD): - versionmap = {'0.91': 'rss091u', - '0.92': 'rss092', - '0.93': 'rss093', - '0.94': 'rss094'} + versionmap = {'0.91': u'rss091u', + '0.92': u'rss092', + '0.93': u'rss093', + '0.94': u'rss094'} #If we're here then this is an RSS feed. #If we don't have a version or have a version that starts with something #other than RSS then there's been a mistake. Correct it. - if not self.version or not self.version.startswith('rss'): + if not self.version or not self.version.startswith(u'rss'): attr_version = attrsD.get('version', '') version = versionmap.get(attr_version) if version: self.version = version elif attr_version.startswith('2.'): - self.version = 'rss20' + self.version = u'rss20' else: - self.version = 'rss' - - def _start_dlhottitles(self, attrsD): - self.version = 'hotrss' + self.version = u'rss' def _start_channel(self, attrsD): self.infeed = 1 self._cdf_common(attrsD) - _start_feedinfo = _start_channel def _cdf_common(self, attrsD): - if attrsD.has_key('lastmod'): + if 'lastmod' in attrsD: self._start_modified({}) self.elementstack[-1][-1] = attrsD['lastmod'] self._end_modified() - if attrsD.has_key('href'): + if 'href' in attrsD: self._start_link({}) self.elementstack[-1][-1] = attrsD['href'] self._end_link() - + def _start_feed(self, attrsD): self.infeed = 1 - versionmap = {'0.1': 'atom01', - '0.2': 'atom02', - '0.3': 'atom03'} + versionmap = {'0.1': u'atom01', + '0.2': u'atom02', + '0.3': u'atom03'} if not self.version: attr_version = attrsD.get('version') version = versionmap.get(attr_version) if version: self.version = version else: - self.version = 'atom' + self.version = u'atom' def _end_channel(self): self.infeed = 0 _end_feed = _end_channel - + def _start_image(self, attrsD): context = self._getContext() if not self.inentry: context.setdefault('image', FeedParserDict()) self.inimage = 1 - self.hasTitle = 0 + self.title_depth = -1 self.push('image', 0) - + def _end_image(self): self.pop('image') self.inimage = 0 @@ -1098,10 +1153,10 @@ class _FeedParserMixin: context = self._getContext() context.setdefault('textinput', FeedParserDict()) self.intextinput = 1 - self.hasTitle = 0 + self.title_depth = -1 self.push('textinput', 0) _start_textInput = _start_textinput - + def _end_textinput(self): self.pop('textinput') self.intextinput = 0 @@ -1183,7 +1238,7 @@ class _FeedParserMixin: value = self.pop('width') try: value = int(value) - except: + except ValueError: value = 0 if self.inimage: context = self._getContext() @@ -1196,7 +1251,7 @@ class _FeedParserMixin: value = self.pop('height') try: value = int(value) - except: + except ValueError: value = 0 if self.inimage: context = self._getContext() @@ -1233,7 +1288,7 @@ class _FeedParserMixin: def _getContext(self): if self.insource: context = self.sourcedata - elif self.inimage and self.feeddata.has_key('image'): + elif self.inimage and 'image' in self.feeddata: context = self.feeddata['image'] elif self.intextinput: context = self.feeddata['textinput'] @@ -1263,26 +1318,27 @@ class _FeedParserMixin: name = detail.get('name') email = detail.get('email') if name and email: - context[key] = '%s (%s)' % (name, email) + context[key] = u'%s (%s)' % (name, email) elif name: context[key] = name elif email: context[key] = email else: author, email = context.get(key), None - if not author: return - emailmatch = re.search(r'''(([a-zA-Z0-9\_\-\.\+]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))(\?subject=\S+)?''', author) + if not author: + return + emailmatch = re.search(ur'''(([a-zA-Z0-9\_\-\.\+]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))(\?subject=\S+)?''', author) if emailmatch: email = emailmatch.group(0) # probably a better way to do the following, but it passes all the tests - author = author.replace(email, '') - author = author.replace('()', '') - author = author.replace('<>', '') - author = author.replace('<>', '') + author = author.replace(email, u'') + author = author.replace(u'()', u'') + author = author.replace(u'<>', u'') + author = author.replace(u'<>', u'') author = author.strip() - if author and (author[0] == '('): + if author and (author[0] == u'('): author = author[1:] - if author and (author[-1] == ')'): + if author and (author[-1] == u')'): author = author[:-1] author = author.strip() if author or email: @@ -1293,7 +1349,7 @@ class _FeedParserMixin: context['%s_detail' % key]['email'] = email def _start_subtitle(self, attrsD): - self.pushContent('subtitle', attrsD, 'text/plain', 1) + self.pushContent('subtitle', attrsD, u'text/plain', 1) _start_tagline = _start_subtitle _start_itunes_subtitle = _start_subtitle @@ -1301,9 +1357,9 @@ class _FeedParserMixin: self.popContent('subtitle') _end_tagline = _end_subtitle _end_itunes_subtitle = _end_subtitle - + def _start_rights(self, attrsD): - self.pushContent('rights', attrsD, 'text/plain', 1) + self.pushContent('rights', attrsD, u'text/plain', 1) _start_dc_rights = _start_rights _start_copyright = _start_rights @@ -1317,14 +1373,13 @@ class _FeedParserMixin: self.push('item', 0) self.inentry = 1 self.guidislink = 0 - self.hasTitle = 0 + self.title_depth = -1 id = self._getAttribute(attrsD, 'rdf:about') if id: context = self._getContext() context['id'] = id self._cdf_common(attrsD) _start_entry = _start_item - _start_product = _start_item def _end_item(self): self.pop('item') @@ -1352,18 +1407,19 @@ class _FeedParserMixin: self.push('published', 1) _start_dcterms_issued = _start_published _start_issued = _start_published + _start_pubdate = _start_published def _end_published(self): value = self.pop('published') self._save('published_parsed', _parse_date(value), overwrite=True) _end_dcterms_issued = _end_published _end_issued = _end_published + _end_pubdate = _end_published def _start_updated(self, attrsD): self.push('updated', 1) _start_modified = _start_updated _start_dcterms_modified = _start_updated - _start_pubdate = _start_updated _start_dc_date = _start_updated _start_lastbuilddate = _start_updated @@ -1373,7 +1429,6 @@ class _FeedParserMixin: self._save('updated_parsed', parsed_value, overwrite=True) _end_modified = _end_updated _end_dcterms_modified = _end_updated - _end_pubdate = _end_updated _end_dc_date = _end_updated _end_lastbuilddate = _end_updated @@ -1396,10 +1451,11 @@ class _FeedParserMixin: context = self._getContext() value = self._getAttribute(attrsD, 'rdf:resource') attrsD = FeedParserDict() - attrsD['rel']='license' - if value: attrsD['href']=value + attrsD['rel'] = u'license' + if value: + attrsD['href']=value context.setdefault('links', []).append(attrsD) - + def _start_creativecommons_license(self, attrsD): self.push('license', 1) _start_creativeCommons_license = _start_creativecommons_license @@ -1408,8 +1464,9 @@ class _FeedParserMixin: value = self.pop('license') context = self._getContext() attrsD = FeedParserDict() - attrsD['rel']='license' - if value: attrsD['href']=value + attrsD['rel'] = u'license' + if value: + attrsD['href'] = value context.setdefault('links', []).append(attrsD) del context['license'] _end_creativeCommons_license = _end_creativecommons_license @@ -1420,17 +1477,17 @@ class _FeedParserMixin: value = FeedParserDict({'relationships': relationships, 'href': href, 'name': name}) if value not in xfn: xfn.append(value) - + def _addTag(self, term, scheme, label): context = self._getContext() tags = context.setdefault('tags', []) - if (not term) and (not scheme) and (not label): return + if (not term) and (not scheme) and (not label): + return value = FeedParserDict({'term': term, 'scheme': scheme, 'label': label}) if value not in tags: tags.append(value) def _start_category(self, attrsD): - if _debug: sys.stderr.write('entering _start_category with %s\n' % repr(attrsD)) term = attrsD.get('term') scheme = attrsD.get('scheme', attrsD.get('domain')) label = attrsD.get('label') @@ -1438,22 +1495,24 @@ class _FeedParserMixin: self.push('category', 1) _start_dc_subject = _start_category _start_keywords = _start_category - + def _start_media_category(self, attrsD): - attrsD.setdefault('scheme', 'http://search.yahoo.com/mrss/category_schema') + attrsD.setdefault('scheme', u'http://search.yahoo.com/mrss/category_schema') self._start_category(attrsD) def _end_itunes_keywords(self): - for term in self.pop('itunes_keywords').split(): - self._addTag(term, 'http://www.itunes.com/', None) - + for term in self.pop('itunes_keywords').split(','): + if term.strip(): + self._addTag(term.strip(), u'http://www.itunes.com/', None) + def _start_itunes_category(self, attrsD): - self._addTag(attrsD.get('text'), 'http://www.itunes.com/', None) + self._addTag(attrsD.get('text'), u'http://www.itunes.com/', None) self.push('category', 1) - + def _end_category(self): value = self.pop('category') - if not value: return + if not value: + return context = self._getContext() tags = context['tags'] if value and len(tags) and not tags[-1]['term']: @@ -1467,76 +1526,77 @@ class _FeedParserMixin: def _start_cloud(self, attrsD): self._getContext()['cloud'] = FeedParserDict(attrsD) - + def _start_link(self, attrsD): - attrsD.setdefault('rel', 'alternate') - if attrsD['rel'] == 'self': - attrsD.setdefault('type', 'application/atom+xml') + attrsD.setdefault('rel', u'alternate') + if attrsD['rel'] == u'self': + attrsD.setdefault('type', u'application/atom+xml') else: - attrsD.setdefault('type', 'text/html') + attrsD.setdefault('type', u'text/html') context = self._getContext() attrsD = self._itsAnHrefDamnIt(attrsD) - if attrsD.has_key('href'): + if 'href' in attrsD: attrsD['href'] = self.resolveURI(attrsD['href']) expectingText = self.infeed or self.inentry or self.insource context.setdefault('links', []) if not (self.inentry and self.inimage): context['links'].append(FeedParserDict(attrsD)) - if attrsD.has_key('href'): + if 'href' in attrsD: expectingText = 0 - if (attrsD.get('rel') == 'alternate') and (self.mapContentType(attrsD.get('type')) in self.html_types): + if (attrsD.get('rel') == u'alternate') and (self.mapContentType(attrsD.get('type')) in self.html_types): context['link'] = attrsD['href'] else: self.push('link', expectingText) - _start_producturl = _start_link def _end_link(self): value = self.pop('link') - context = self._getContext() - _end_producturl = _end_link def _start_guid(self, attrsD): self.guidislink = (attrsD.get('ispermalink', 'true') == 'true') self.push('id', 1) + _start_id = _start_guid def _end_guid(self): value = self.pop('id') - self._save('guidislink', self.guidislink and not self._getContext().has_key('link')) + self._save('guidislink', self.guidislink and 'link' not in self._getContext()) if self.guidislink: # guid acts as link, but only if 'ispermalink' is not present or is 'true', # and only if the item doesn't already have a link element self._save('link', value) + _end_id = _end_guid def _start_title(self, attrsD): - if self.svgOK: return self.unknown_starttag('title', attrsD.items()) - self.pushContent('title', attrsD, 'text/plain', self.infeed or self.inentry or self.insource) + if self.svgOK: + return self.unknown_starttag('title', attrsD.items()) + self.pushContent('title', attrsD, u'text/plain', self.infeed or self.inentry or self.insource) _start_dc_title = _start_title _start_media_title = _start_title def _end_title(self): - if self.svgOK: return + if self.svgOK: + return value = self.popContent('title') - if not value: return - context = self._getContext() - self.hasTitle = 1 + if not value: + return + self.title_depth = self.depth _end_dc_title = _end_title def _end_media_title(self): - hasTitle = self.hasTitle + title_depth = self.title_depth self._end_title() - self.hasTitle = hasTitle + self.title_depth = title_depth def _start_description(self, attrsD): context = self._getContext() - if context.has_key('summary'): + if 'summary' in context: self._summaryKey = 'content' self._start_content(attrsD) else: - self.pushContent('description', attrsD, 'text/html', self.infeed or self.inentry or self.insource) + self.pushContent('description', attrsD, u'text/html', self.infeed or self.inentry or self.insource) _start_dc_description = _start_description def _start_abstract(self, attrsD): - self.pushContent('description', attrsD, 'text/plain', self.infeed or self.inentry or self.insource) + self.pushContent('description', attrsD, u'text/plain', self.infeed or self.inentry or self.insource) def _end_description(self): if self._summaryKey == 'content': @@ -1548,7 +1608,7 @@ class _FeedParserMixin: _end_dc_description = _end_description def _start_info(self, attrsD): - self.pushContent('info', attrsD, 'text/plain', 1) + self.pushContent('info', attrsD, u'text/plain', 1) _start_feedburner_browserfriendly = _start_info def _end_info(self): @@ -1558,7 +1618,7 @@ class _FeedParserMixin: def _start_generator(self, attrsD): if attrsD: attrsD = self._itsAnHrefDamnIt(attrsD) - if attrsD.has_key('href'): + if 'href' in attrsD: attrsD['href'] = self.resolveURI(attrsD['href']) self._getContext()['generator_detail'] = FeedParserDict(attrsD) self.push('generator', 1) @@ -1566,9 +1626,9 @@ class _FeedParserMixin: def _end_generator(self): value = self.pop('generator') context = self._getContext() - if context.has_key('generator_detail'): + if 'generator_detail' in context: context['generator_detail']['name'] = value - + def _start_admin_generatoragent(self, attrsD): self.push('generator', 1) value = self._getAttribute(attrsD, 'rdf:resource') @@ -1583,15 +1643,15 @@ class _FeedParserMixin: if value: self.elementstack[-1][2].append(value) self.pop('errorreportsto') - + def _start_summary(self, attrsD): context = self._getContext() - if context.has_key('summary'): + if 'summary' in context: self._summaryKey = 'content' self._start_content(attrsD) else: self._summaryKey = 'summary' - self.pushContent(self._summaryKey, attrsD, 'text/plain', 1) + self.pushContent(self._summaryKey, attrsD, u'text/plain', 1) _start_itunes_summary = _start_summary def _end_summary(self): @@ -1601,49 +1661,46 @@ class _FeedParserMixin: self.popContent(self._summaryKey or 'summary') self._summaryKey = None _end_itunes_summary = _end_summary - + def _start_enclosure(self, attrsD): attrsD = self._itsAnHrefDamnIt(attrsD) context = self._getContext() - attrsD['rel']='enclosure' + attrsD['rel'] = u'enclosure' context.setdefault('links', []).append(FeedParserDict(attrsD)) - + def _start_source(self, attrsD): if 'url' in attrsD: - # This means that we're processing a source element from an RSS 2.0 feed - self.sourcedata['href'] = attrsD[u'url'] + # This means that we're processing a source element from an RSS 2.0 feed + self.sourcedata['href'] = attrsD[u'url'] self.push('source', 1) self.insource = 1 - self.hasTitle = 0 + self.title_depth = -1 def _end_source(self): self.insource = 0 value = self.pop('source') if value: - self.sourcedata['title'] = value + self.sourcedata['title'] = value self._getContext()['source'] = copy.deepcopy(self.sourcedata) self.sourcedata.clear() def _start_content(self, attrsD): - self.pushContent('content', attrsD, 'text/plain', 1) + self.pushContent('content', attrsD, u'text/plain', 1) src = attrsD.get('src') if src: self.contentparams['src'] = src self.push('content', 1) - def _start_prodlink(self, attrsD): - self.pushContent('content', attrsD, 'text/html', 1) - def _start_body(self, attrsD): - self.pushContent('content', attrsD, 'application/xhtml+xml', 1) + self.pushContent('content', attrsD, u'application/xhtml+xml', 1) _start_xhtml_body = _start_body def _start_content_encoded(self, attrsD): - self.pushContent('content', attrsD, 'text/html', 1) + self.pushContent('content', attrsD, u'text/html', 1) _start_fullitem = _start_content_encoded def _end_content(self): - copyToSummary = self.mapContentType(self.contentparams.get('type')) in (['text/plain'] + self.html_types) + copyToSummary = self.mapContentType(self.contentparams.get('type')) in ([u'text/plain'] + self.html_types) value = self.popContent('content') if copyToSummary: self._save('summary', value) @@ -1652,14 +1709,15 @@ class _FeedParserMixin: _end_xhtml_body = _end_content _end_content_encoded = _end_content _end_fullitem = _end_content - _end_prodlink = _end_content def _start_itunes_image(self, attrsD): self.push('itunes_image', 0) if attrsD.get('href'): self._getContext()['image'] = FeedParserDict({'href': attrsD.get('href')}) + elif attrsD.get('url'): + self._getContext()['image'] = FeedParserDict({'href': attrsD.get('url')}) _start_itunes_link = _start_itunes_image - + def _end_itunes_block(self): value = self.pop('itunes_block', 0) self._getContext()['itunes_block'] = (value == 'yes') and 1 or 0 @@ -1685,8 +1743,8 @@ class _FeedParserMixin: def _end_media_thumbnail(self): url = self.pop('url') context = self._getContext() - if url is not None and len(url.strip()) != 0: - if not context['media_thumbnail'][-1].has_key('url'): + if url != None and len(url.strip()) != 0: + if 'url' not in context['media_thumbnail'][-1]: context['media_thumbnail'][-1]['url'] = url def _start_media_player(self, attrsD): @@ -1712,32 +1770,35 @@ class _FeedParserMixin: if _XML_AVAILABLE: class _StrictFeedParser(_FeedParserMixin, xml.sax.handler.ContentHandler): def __init__(self, baseuri, baselang, encoding): - if _debug: sys.stderr.write('trying StrictFeedParser\n') xml.sax.handler.ContentHandler.__init__(self) _FeedParserMixin.__init__(self, baseuri, baselang, encoding) self.bozo = 0 self.exc = None self.decls = {} - + def startPrefixMapping(self, prefix, uri): + if not uri: + return + # Jython uses '' instead of None; standardize on None + prefix = prefix or None self.trackNamespace(prefix, uri) - if uri == 'http://www.w3.org/1999/xlink': - self.decls['xmlns:'+prefix] = uri - + if prefix and uri == 'http://www.w3.org/1999/xlink': + self.decls['xmlns:' + prefix] = uri + def startElementNS(self, name, qname, attrs): namespace, localname = name lowernamespace = str(namespace or '').lower() - if lowernamespace.find('backend.userland.com/rss') <> -1: + if lowernamespace.find(u'backend.userland.com/rss') <> -1: # match any backend.userland.com namespace - namespace = 'http://backend.userland.com/rss' + namespace = u'http://backend.userland.com/rss' lowernamespace = namespace if qname and qname.find(':') > 0: givenprefix = qname.split(':')[0] else: givenprefix = None prefix = self._matchnamespaces.get(lowernamespace, givenprefix) - if givenprefix and (prefix is None or (prefix == '' and lowernamespace == '')) and not self.namespacesInUse.has_key(givenprefix): - raise UndeclaredNamespace, "'%s' is not associated with a namespace" % givenprefix + if givenprefix and (prefix == None or (prefix == '' and lowernamespace == '')) and givenprefix not in self.namespacesInUse: + raise UndeclaredNamespace, "'%s' is not associated with a namespace" % givenprefix localname = str(localname).lower() # qname implementation is horribly broken in Python 2.1 (it @@ -1757,12 +1818,11 @@ if _XML_AVAILABLE: localname = prefix.lower() + ':' + localname elif namespace and not qname: #Expat for name,value in self.namespacesInUse.items(): - if name and value == namespace: - localname = name + ':' + localname - break - if _debug: sys.stderr.write('startElementNS: qname = %s, namespace = %s, givenprefix = %s, prefix = %s, attrs = %s, localname = %s\n' % (qname, namespace, givenprefix, prefix, attrs.items(), localname)) + if name and value == namespace: + localname = name + ':' + localname + break - for (namespace, attrlocalname), attrvalue in attrs._attrs.items(): + for (namespace, attrlocalname), attrvalue in attrs.items(): lowernamespace = (namespace or '').lower() prefix = self._matchnamespaces.get(lowernamespace, '') if prefix: @@ -1787,9 +1847,9 @@ if _XML_AVAILABLE: localname = prefix + ':' + localname elif namespace and not qname: #Expat for name,value in self.namespacesInUse.items(): - if name and value == namespace: - localname = name + ':' + localname - break + if name and value == namespace: + localname = name + ':' + localname + break localname = str(localname).lower() self.unknown_endtag(localname) @@ -1797,6 +1857,9 @@ if _XML_AVAILABLE: self.bozo = 1 self.exc = exc + # drv_libxml2 calls warning() in some cases + warning = error + def fatalError(self, exc): self.error(exc) raise exc @@ -1804,16 +1867,15 @@ if _XML_AVAILABLE: class _BaseHTMLProcessor(sgmllib.SGMLParser): special = re.compile('''[<>'"]''') bare_ampersand = re.compile("&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;)") - elements_no_end_tag = [ - 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', + elements_no_end_tag = set([ + 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr' - ] + ]) def __init__(self, encoding, _type): self.encoding = encoding self._type = _type - if _debug: sys.stderr.write('entering BaseHTMLProcessor, encoding=%s\n' % self.encoding) sgmllib.SGMLParser.__init__(self) def reset(self): @@ -1827,8 +1889,21 @@ class _BaseHTMLProcessor(sgmllib.SGMLParser): else: return '<' + tag + '></' + tag + '>' + # By declaring these methods and overriding their compiled code + # with the code from sgmllib, the original code will execute in + # feedparser's scope instead of sgmllib's. This means that the + # `tagfind` and `charref` regular expressions will be found as + # they're declared above, not as they're declared in sgmllib. + def goahead(self, i): + pass + goahead.func_code = sgmllib.SGMLParser.goahead.func_code + + def __parse_starttag(self, i): + pass + __parse_starttag.func_code = sgmllib.SGMLParser.parse_starttag.func_code + def parse_starttag(self,i): - j=sgmllib.SGMLParser.parse_starttag(self, i) + j = self.__parse_starttag(i) if self._type == 'application/xhtml+xml': if j>2 and self.rawdata[j-2:j]=='/>': self.unknown_endtag(self.lasttag) @@ -1836,23 +1911,23 @@ class _BaseHTMLProcessor(sgmllib.SGMLParser): def feed(self, data): data = re.compile(r'<!((?!DOCTYPE|--|\[))', re.IGNORECASE).sub(r'<!\1', data) - #data = re.sub(r'<(\S+?)\s*?/>', self._shorttag_replace, data) # bug [ 1399464 ] Bad regexp for _shorttag_replace - data = re.sub(r'<([^<>\s]+?)\s*/>', self._shorttag_replace, data) + data = re.sub(r'<([^<>\s]+?)\s*/>', self._shorttag_replace, data) data = data.replace(''', "'") data = data.replace('"', '"') try: bytes if bytes is str: raise NameError - self.encoding = self.encoding + '_INVALID_PYTHON_3' + self.encoding = self.encoding + u'_INVALID_PYTHON_3' except NameError: - if self.encoding and type(data) == type(u''): + if self.encoding and isinstance(data, unicode): data = data.encode(self.encoding) sgmllib.SGMLParser.feed(self, data) sgmllib.SGMLParser.close(self) def normalize_attrs(self, attrs): - if not attrs: return attrs + if not attrs: + return attrs # utility method to be called by descendants attrs = dict([(k.lower(), v) for k, v in attrs]).items() attrs = [(k, k in ('rel', 'type') and v.lower() or v) for k, v in attrs] @@ -1863,7 +1938,6 @@ class _BaseHTMLProcessor(sgmllib.SGMLParser): # called for each start tag # attrs is a list of (attr, value) tuples # e.g. for <pre class='screen'>, tag='pre', attrs=[('class', 'screen')] - if _debug: sys.stderr.write('_BaseHTMLProcessor, unknown_starttag, tag=%s\n' % tag) uattrs = [] strattrs='' if attrs: @@ -1871,11 +1945,8 @@ class _BaseHTMLProcessor(sgmllib.SGMLParser): value=value.replace('>','>').replace('<','<').replace('"','"') value = self.bare_ampersand.sub("&", value) # thanks to Kevin Marks for this breathtaking hack to deal with (valid) high-bit attribute values in UTF-8 feeds - if type(value) != type(u''): - try: - value = unicode(value, self.encoding) - except: - value = unicode(value, 'iso-8859-1') + if not isinstance(value, unicode): + value = value.decode(self.encoding, 'ignore') try: # Currently, in Python 3 the key is already a str, and cannot be decoded again uattrs.append((unicode(key, self.encoding), value)) @@ -1884,65 +1955,65 @@ class _BaseHTMLProcessor(sgmllib.SGMLParser): strattrs = u''.join([u' %s="%s"' % (key, value) for key, value in uattrs]) if self.encoding: try: - strattrs=strattrs.encode(self.encoding) - except: + strattrs = strattrs.encode(self.encoding) + except (UnicodeEncodeError, LookupError): pass if tag in self.elements_no_end_tag: - self.pieces.append('<%(tag)s%(strattrs)s />' % locals()) + self.pieces.append('<%s%s />' % (tag, strattrs)) else: - self.pieces.append('<%(tag)s%(strattrs)s>' % locals()) + self.pieces.append('<%s%s>' % (tag, strattrs)) def unknown_endtag(self, tag): # called for each end tag, e.g. for </pre>, tag will be 'pre' # Reconstruct the original end tag. if tag not in self.elements_no_end_tag: - self.pieces.append("</%(tag)s>" % locals()) + self.pieces.append("</%s>" % tag) def handle_charref(self, ref): # called for each character reference, e.g. for ' ', ref will be '160' # Reconstruct the original character reference. + ref = ref.lower() if ref.startswith('x'): - value = unichr(int(ref[1:],16)) + value = int(ref[1:], 16) else: - value = unichr(int(ref)) + value = int(ref) - if value in _cp1252.keys(): + if value in _cp1252: self.pieces.append('&#%s;' % hex(ord(_cp1252[value]))[1:]) else: - self.pieces.append('&#%(ref)s;' % locals()) - + self.pieces.append('&#%s;' % ref) + def handle_entityref(self, ref): # called for each entity reference, e.g. for '©', ref will be 'copy' # Reconstruct the original entity reference. - if name2codepoint.has_key(ref): - self.pieces.append('&%(ref)s;' % locals()) + if ref in name2codepoint or ref == 'apos': + self.pieces.append('&%s;' % ref) else: - self.pieces.append('&%(ref)s' % locals()) + self.pieces.append('&%s' % ref) def handle_data(self, text): # called for each block of plain text, i.e. outside of any tag and # not containing any character or entity references # Store the original text verbatim. - if _debug: sys.stderr.write('_BaseHTMLProcessor, handle_data, text=%s\n' % text) self.pieces.append(text) - + def handle_comment(self, text): # called for each HTML comment, e.g. <!-- insert Javascript code here --> # Reconstruct the original comment. - self.pieces.append('<!--%(text)s-->' % locals()) - + self.pieces.append('<!--%s-->' % text) + def handle_pi(self, text): # called for each processing instruction, e.g. <?instruction> # Reconstruct original processing instruction. - self.pieces.append('<?%(text)s>' % locals()) + self.pieces.append('<?%s>' % text) def handle_decl(self, text): # called for the DOCTYPE, if present, e.g. # <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" # "http://www.w3.org/TR/html4/loose.dtd"> # Reconstruct original DOCTYPE - self.pieces.append('<!%(text)s>' % locals()) - + self.pieces.append('<!%s>' % text) + _new_declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9:]*\s*').match def _scan_name(self, i, declstartpos): rawdata = self.rawdata @@ -1971,6 +2042,14 @@ class _BaseHTMLProcessor(sgmllib.SGMLParser): '''Return processed HTML as a single string''' return ''.join([str(p) for p in self.pieces]) + def parse_declaration(self, i): + try: + return sgmllib.SGMLParser.parse_declaration(self, i) + except sgmllib.SGMLParseError: + # escape the doctype declaration and continue parsing + self.handle_data('<') + return i+1 + class _LooseFeedParser(_FeedParserMixin, _BaseHTMLProcessor): def __init__(self, baseuri, baselang, encoding, entities): sgmllib.SGMLParser.__init__(self) @@ -1991,14 +2070,14 @@ class _LooseFeedParser(_FeedParserMixin, _BaseHTMLProcessor): data = data.replace('"', '"') data = data.replace(''', ''') data = data.replace(''', ''') - if self.contentparams.has_key('type') and not self.contentparams.get('type', 'xml').endswith('xml'): + if not self.contentparams.get('type', u'xml').endswith(u'xml'): data = data.replace('<', '<') data = data.replace('>', '>') data = data.replace('&', '&') data = data.replace('"', '"') data = data.replace(''', "'") return data - + def strattrs(self, attrs): return ''.join([' %s="%s"' % (n,v.replace('"','"')) for n,v in attrs]) @@ -2009,25 +2088,25 @@ class _MicroformatsParser: NODE = 4 EMAIL = 5 - known_xfn_relationships = ['contact', 'acquaintance', 'friend', 'met', 'co-worker', 'coworker', 'colleague', 'co-resident', 'coresident', 'neighbor', 'child', 'parent', 'sibling', 'brother', 'sister', 'spouse', 'wife', 'husband', 'kin', 'relative', 'muse', 'crush', 'date', 'sweetheart', 'me'] - known_binary_extensions = ['zip','rar','exe','gz','tar','tgz','tbz2','bz2','z','7z','dmg','img','sit','sitx','hqx','deb','rpm','bz2','jar','rar','iso','bin','msi','mp2','mp3','ogg','ogm','mp4','m4v','m4a','avi','wma','wmv'] + known_xfn_relationships = set(['contact', 'acquaintance', 'friend', 'met', 'co-worker', 'coworker', 'colleague', 'co-resident', 'coresident', 'neighbor', 'child', 'parent', 'sibling', 'brother', 'sister', 'spouse', 'wife', 'husband', 'kin', 'relative', 'muse', 'crush', 'date', 'sweetheart', 'me']) + known_binary_extensions = set(['zip','rar','exe','gz','tar','tgz','tbz2','bz2','z','7z','dmg','img','sit','sitx','hqx','deb','rpm','bz2','jar','rar','iso','bin','msi','mp2','mp3','ogg','ogm','mp4','m4v','m4a','avi','wma','wmv']) def __init__(self, data, baseuri, encoding): self.document = BeautifulSoup.BeautifulSoup(data) self.baseuri = baseuri self.encoding = encoding - if type(data) == type(u''): + if isinstance(data, unicode): data = data.encode(encoding) self.tags = [] self.enclosures = [] self.xfn = [] self.vcard = None - + def vcardEscape(self, s): - if type(s) in (type(''), type(u'')): + if isinstance(s, basestring): s = s.replace(',', '\\,').replace(';', '\\;').replace('\n', '\\n') return s - + def vcardFold(self, s): s = re.sub(';+$', '', s) sFolded = '' @@ -2043,14 +2122,14 @@ class _MicroformatsParser: def normalize(self, s): return re.sub(r'\s+', ' ', s).strip() - + def unique(self, aList): results = [] for element in aList: if element not in results: results.append(element) return results - + def toISO8601(self, dt): return time.strftime('%Y-%m-%dT%H:%M:%SZ', dt) @@ -2088,12 +2167,18 @@ class _MicroformatsParser: arResults.append(node) bFound = (len(arResults) != 0) if not bFound: - if bAllowMultiple: return [] - elif iPropertyType == self.STRING: return '' - elif iPropertyType == self.DATE: return None - elif iPropertyType == self.URI: return '' - elif iPropertyType == self.NODE: return None - else: return None + if bAllowMultiple: + return [] + elif iPropertyType == self.STRING: + return '' + elif iPropertyType == self.DATE: + return None + elif iPropertyType == self.URI: + return '' + elif iPropertyType == self.NODE: + return None + else: + return None arValues = [] for elmResult in arResults: sValue = None @@ -2113,9 +2198,12 @@ class _MicroformatsParser: if sValue: sValue = bNormalize and self.normalize(sValue) or sValue.strip() if (not sValue) and (iPropertyType == self.URI): - if sNodeName == 'a': sValue = elmResult.get('href') - elif sNodeName == 'img': sValue = elmResult.get('src') - elif sNodeName == 'object': sValue = elmResult.get('data') + if sNodeName == 'a': + sValue = elmResult.get('href') + elif sNodeName == 'img': + sValue = elmResult.get('src') + elif sNodeName == 'object': + sValue = elmResult.get('data') if sValue: sValue = bNormalize and self.normalize(sValue) or sValue.strip() if (not sValue) and (sNodeName == 'img'): @@ -2129,7 +2217,8 @@ class _MicroformatsParser: sValue = sValue.replace('\r', '\n') if sValue: sValue = bNormalize and self.normalize(sValue) or sValue.strip() - if not sValue: continue + if not sValue: + continue if iPropertyType == self.DATE: sValue = _parse_date_iso8601(sValue) if bAllowMultiple: @@ -2140,21 +2229,21 @@ class _MicroformatsParser: def findVCards(self, elmRoot, bAgentParsing=0): sVCards = '' - + if not bAgentParsing: arCards = self.getPropertyValue(elmRoot, 'vcard', bAllowMultiple=1) else: arCards = [elmRoot] - + for elmCard in arCards: arLines = [] - + def processSingleString(sProperty): sValue = self.getPropertyValue(elmCard, sProperty, self.STRING, bAutoEscape=1).decode(self.encoding) if sValue: arLines.append(self.vcardFold(sProperty.upper() + ':' + sValue)) return sValue or u'' - + def processSingleURI(sProperty): sValue = self.getPropertyValue(elmCard, sProperty, self.URI) if sValue: @@ -2177,7 +2266,7 @@ class _MicroformatsParser: if sContentType: sContentType = ';TYPE=' + sContentType.upper() arLines.append(self.vcardFold(sProperty.upper() + sEncoding + sContentType + sValueKey + ':' + sValue)) - + def processTypeValue(sProperty, arDefaultType, arForceType=None): arResults = self.getPropertyValue(elmCard, sProperty, bAllowMultiple=1) for elmResult in arResults: @@ -2189,7 +2278,7 @@ class _MicroformatsParser: sValue = self.getPropertyValue(elmResult, 'value', self.EMAIL, 0) if sValue: arLines.append(self.vcardFold(sProperty.upper() + ';TYPE=' + ','.join(arType) + ':' + sValue)) - + # AGENT # must do this before all other properties because it is destructive # (removes nested class="vcard" nodes so they don't interfere with @@ -2208,10 +2297,10 @@ class _MicroformatsParser: sAgentValue = self.getPropertyValue(elmAgent, 'value', self.URI, bAutoEscape=1); if sAgentValue: arLines.append(self.vcardFold('AGENT;VALUE=uri:' + sAgentValue)) - + # FN (full name) sFN = processSingleString('fn') - + # N (name) elmName = self.getPropertyValue(elmCard, 'n') if elmName: @@ -2220,7 +2309,7 @@ class _MicroformatsParser: arAdditionalNames = self.getPropertyValue(elmName, 'additional-name', self.STRING, 1, 1) + self.getPropertyValue(elmName, 'additional-names', self.STRING, 1, 1) arHonorificPrefixes = self.getPropertyValue(elmName, 'honorific-prefix', self.STRING, 1, 1) + self.getPropertyValue(elmName, 'honorific-prefixes', self.STRING, 1, 1) arHonorificSuffixes = self.getPropertyValue(elmName, 'honorific-suffix', self.STRING, 1, 1) + self.getPropertyValue(elmName, 'honorific-suffixes', self.STRING, 1, 1) - arLines.append(self.vcardFold('N:' + sFamilyName + ';' + + arLines.append(self.vcardFold('N:' + sFamilyName + ';' + sGivenName + ';' + ','.join(arAdditionalNames) + ';' + ','.join(arHonorificPrefixes) + ';' + @@ -2237,25 +2326,25 @@ class _MicroformatsParser: arLines.append(self.vcardFold('N:' + arNames[0] + ';' + arNames[1])) else: arLines.append(self.vcardFold('N:' + arNames[1] + ';' + arNames[0])) - + # SORT-STRING sSortString = self.getPropertyValue(elmCard, 'sort-string', self.STRING, bAutoEscape=1) if sSortString: arLines.append(self.vcardFold('SORT-STRING:' + sSortString)) - + # NICKNAME arNickname = self.getPropertyValue(elmCard, 'nickname', self.STRING, 1, 1) if arNickname: arLines.append(self.vcardFold('NICKNAME:' + ','.join(arNickname))) - + # PHOTO processSingleURI('photo') - + # BDAY dtBday = self.getPropertyValue(elmCard, 'bday', self.DATE) if dtBday: arLines.append(self.vcardFold('BDAY:' + self.toISO8601(dtBday))) - + # ADR (address) arAdr = self.getPropertyValue(elmCard, 'adr', bAllowMultiple=1) for elmAdr in arAdr: @@ -2277,38 +2366,38 @@ class _MicroformatsParser: sRegion + ';' + sPostalCode + ';' + sCountryName)) - + # LABEL processTypeValue('label', ['intl','postal','parcel','work']) - + # TEL (phone number) processTypeValue('tel', ['voice']) - + # EMAIL processTypeValue('email', ['internet'], ['internet']) - + # MAILER processSingleString('mailer') - + # TZ (timezone) processSingleString('tz') - + # GEO (geographical information) elmGeo = self.getPropertyValue(elmCard, 'geo') if elmGeo: sLatitude = self.getPropertyValue(elmGeo, 'latitude', self.STRING, 0, 1) sLongitude = self.getPropertyValue(elmGeo, 'longitude', self.STRING, 0, 1) arLines.append(self.vcardFold('GEO:' + sLatitude + ';' + sLongitude)) - + # TITLE processSingleString('title') - + # ROLE processSingleString('role') # LOGO processSingleURI('logo') - + # ORG (organization) elmOrg = self.getPropertyValue(elmCard, 'org') if elmOrg: @@ -2322,49 +2411,58 @@ class _MicroformatsParser: else: arOrganizationUnit = self.getPropertyValue(elmOrg, 'organization-unit', self.STRING, 1, 1) arLines.append(self.vcardFold('ORG:' + sOrganizationName + ';' + ';'.join(arOrganizationUnit))) - + # CATEGORY arCategory = self.getPropertyValue(elmCard, 'category', self.STRING, 1, 1) + self.getPropertyValue(elmCard, 'categories', self.STRING, 1, 1) if arCategory: arLines.append(self.vcardFold('CATEGORIES:' + ','.join(arCategory))) - + # NOTE processSingleString('note') - + # REV processSingleString('rev') - + # SOUND processSingleURI('sound') - + # UID processSingleString('uid') - + # URL processSingleURI('url') - + # CLASS processSingleString('class') - + # KEY processSingleURI('key') - + if arLines: arLines = [u'BEGIN:vCard',u'VERSION:3.0'] + arLines + [u'END:vCard'] + # XXX - this is super ugly; properly fix this with issue 148 + for i, s in enumerate(arLines): + if not isinstance(s, unicode): + arLines[i] = s.decode('utf-8', 'ignore') sVCards += u'\n'.join(arLines) + u'\n' - + return sVCards.strip() - + def isProbablyDownloadable(self, elm): attrsD = elm.attrMap - if not attrsD.has_key('href'): return 0 + if 'href' not in attrsD: + return 0 linktype = attrsD.get('type', '').strip() if linktype.startswith('audio/') or \ linktype.startswith('video/') or \ (linktype.startswith('application/') and not linktype.endswith('xml')): return 1 - path = urlparse.urlparse(attrsD['href'])[2] - if path.find('.') == -1: return 0 + try: + path = urlparse.urlparse(attrsD['href'])[2] + except ValueError: + return 0 + if path.find('.') == -1: + return 0 fileext = path.split('.').pop().lower() return fileext in self.known_binary_extensions @@ -2372,13 +2470,18 @@ class _MicroformatsParser: all = lambda x: 1 for elm in self.document(all, {'rel': re.compile(r'\btag\b')}): href = elm.get('href') - if not href: continue + if not href: + continue urlscheme, domain, path, params, query, fragment = \ urlparse.urlparse(_urljoin(self.baseuri, href)) segments = path.split('/') tag = segments.pop() if not tag: - tag = segments.pop() + if segments: + tag = segments.pop() + else: + # there are no tags + continue tagscheme = urlparse.urlunparse((urlscheme, domain, '/'.join(segments), '', '', '')) if not tagscheme.endswith('/'): tagscheme += '/' @@ -2388,7 +2491,8 @@ class _MicroformatsParser: all = lambda x: 1 enclosure_match = re.compile(r'\benclosure\b') for elm in self.document(all, {'href': re.compile(r'.+')}): - if not enclosure_match.search(elm.get('rel', '')) and not self.isProbablyDownloadable(elm): continue + if not enclosure_match.search(elm.get('rel', u'')) and not self.isProbablyDownloadable(elm): + continue if elm.attrMap not in self.enclosures: self.enclosures.append(elm.attrMap) if elm.string and not elm.get('title'): @@ -2397,17 +2501,14 @@ class _MicroformatsParser: def findXFN(self): all = lambda x: 1 for elm in self.document(all, {'rel': re.compile('.+'), 'href': re.compile('.+')}): - rels = elm.get('rel', '').split() - xfn_rels = [] - for rel in rels: - if rel in self.known_xfn_relationships: - xfn_rels.append(rel) + rels = elm.get('rel', u'').split() + xfn_rels = [r for r in rels if r in self.known_xfn_relationships] if xfn_rels: self.xfn.append({"relationships": xfn_rels, "href": elm.get('href', ''), "name": elm.string}) def _parseMicroformats(htmlSource, baseURI, encoding): - if not BeautifulSoup: return - if _debug: sys.stderr.write('entering _parseMicroformats\n') + if not BeautifulSoup: + return try: p = _MicroformatsParser(htmlSource, baseURI, encoding) except UnicodeEncodeError: @@ -2421,7 +2522,7 @@ def _parseMicroformats(htmlSource, baseURI, encoding): return {"tags": p.tags, "enclosures": p.enclosures, "xfn": p.xfn, "vcard": p.vcard} class _RelativeURIResolver(_BaseHTMLProcessor): - relative_uris = [('a', 'href'), + relative_uris = set([('a', 'href'), ('applet', 'codebase'), ('area', 'href'), ('blockquote', 'cite'), @@ -2445,25 +2546,24 @@ class _RelativeURIResolver(_BaseHTMLProcessor): ('object', 'data'), ('object', 'usemap'), ('q', 'cite'), - ('script', 'src')] + ('script', 'src'), + ('video', 'poster')]) def __init__(self, baseuri, encoding, _type): _BaseHTMLProcessor.__init__(self, encoding, _type) self.baseuri = baseuri def resolveURI(self, uri): - return _makeSafeAbsoluteURI(_urljoin(self.baseuri, uri.strip())) - + return _makeSafeAbsoluteURI(self.baseuri, uri.strip()) + def unknown_starttag(self, tag, attrs): - if _debug: - sys.stderr.write('tag: [%s] with attributes: [%s]\n' % (tag, str(attrs))) attrs = self.normalize_attrs(attrs) attrs = [(key, ((tag, key) in self.relative_uris) and self.resolveURI(value) or value) for key, value in attrs] _BaseHTMLProcessor.unknown_starttag(self, tag, attrs) def _resolveRelativeURIs(htmlSource, baseURI, encoding, _type): - if _debug: - sys.stderr.write('entering _resolveRelativeURIs\n') + if not _SGML_AVAILABLE: + return htmlSource p = _RelativeURIResolver(baseURI, encoding, _type) p.feed(htmlSource) @@ -2472,20 +2572,30 @@ def _resolveRelativeURIs(htmlSource, baseURI, encoding, _type): def _makeSafeAbsoluteURI(base, rel=None): # bail if ACCEPTABLE_URI_SCHEMES is empty if not ACCEPTABLE_URI_SCHEMES: - return _urljoin(base, rel or u'') + try: + return _urljoin(base, rel or u'') + except ValueError: + return u'' if not base: return rel or u'' if not rel: - if base.strip().split(':', 1)[0] not in ACCEPTABLE_URI_SCHEMES: + try: + scheme = urlparse.urlparse(base)[0] + except ValueError: return u'' - return base - uri = _urljoin(base, rel) + if not scheme or scheme in ACCEPTABLE_URI_SCHEMES: + return base + return u'' + try: + uri = _urljoin(base, rel) + except ValueError: + return u'' if uri.strip().split(':', 1)[0] not in ACCEPTABLE_URI_SCHEMES: return u'' return uri class _HTMLSanitizer(_BaseHTMLProcessor): - acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area', + acceptable_elements = set(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'big', 'blockquote', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn', @@ -2497,9 +2607,9 @@ class _HTMLSanitizer(_BaseHTMLProcessor): 'p', 'pre', 'progress', 'q', 's', 'samp', 'section', 'select', 'small', 'sound', 'source', 'spacer', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'time', 'tfoot', - 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'video', 'noscript'] + 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'video', 'noscript']) - acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey', + acceptable_attributes = set(['abbr', 'accept', 'accept-charset', 'accesskey', 'action', 'align', 'alt', 'autocomplete', 'autofocus', 'axis', 'background', 'balance', 'bgcolor', 'bgproperties', 'border', 'bordercolor', 'bordercolordark', 'bordercolorlight', 'bottompadding', @@ -2514,17 +2624,17 @@ class _HTMLSanitizer(_BaseHTMLProcessor): 'loop', 'loopcount', 'loopend', 'loopstart', 'low', 'lowsrc', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'open', 'optimum', 'pattern', 'ping', 'point-size', - 'prompt', 'pqg', 'radiogroup', 'readonly', 'rel', 'repeat-max', - 'repeat-min', 'replace', 'required', 'rev', 'rightspacing', 'rows', - 'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', 'span', 'src', - 'start', 'step', 'summary', 'suppress', 'tabindex', 'target', 'template', - 'title', 'toppadding', 'type', 'unselectable', 'usemap', 'urn', 'valign', - 'value', 'variable', 'volume', 'vspace', 'vrml', 'width', 'wrap', - 'xml:lang'] + 'poster', 'pqg', 'preload', 'prompt', 'radiogroup', 'readonly', 'rel', + 'repeat-max', 'repeat-min', 'replace', 'required', 'rev', 'rightspacing', + 'rows', 'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', 'span', + 'src', 'start', 'step', 'summary', 'suppress', 'tabindex', 'target', + 'template', 'title', 'toppadding', 'type', 'unselectable', 'usemap', + 'urn', 'valign', 'value', 'variable', 'volume', 'vspace', 'vrml', + 'width', 'wrap', 'xml:lang']) - unacceptable_elements_with_end_tag = ['script', 'applet', 'style'] + unacceptable_elements_with_end_tag = set(['script', 'applet', 'style']) - acceptable_css_properties = ['azimuth', 'background-color', + acceptable_css_properties = set(['azimuth', 'background-color', 'border-bottom-color', 'border-collapse', 'border-color', 'border-left-color', 'border-right-color', 'border-top-color', 'clear', 'color', 'cursor', 'direction', 'display', 'elevation', 'float', 'font', @@ -2534,26 +2644,26 @@ class _HTMLSanitizer(_BaseHTMLProcessor): 'speak', 'speak-header', 'speak-numeral', 'speak-punctuation', 'speech-rate', 'stress', 'text-align', 'text-decoration', 'text-indent', 'unicode-bidi', 'vertical-align', 'voice-family', 'volume', - 'white-space', 'width'] + 'white-space', 'width']) # survey of common keywords found in feeds - acceptable_css_keywords = ['auto', 'aqua', 'black', 'block', 'blue', + acceptable_css_keywords = set(['auto', 'aqua', 'black', 'block', 'blue', 'bold', 'both', 'bottom', 'brown', 'center', 'collapse', 'dashed', 'dotted', 'fuchsia', 'gray', 'green', '!important', 'italic', 'left', 'lime', 'maroon', 'medium', 'none', 'navy', 'normal', 'nowrap', 'olive', 'pointer', 'purple', 'red', 'right', 'solid', 'silver', 'teal', 'top', - 'transparent', 'underline', 'white', 'yellow'] + 'transparent', 'underline', 'white', 'yellow']) valid_css_values = re.compile('^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|' + '\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$') - mathml_elements = ['annotation', 'annotation-xml', 'maction', 'math', + mathml_elements = set(['annotation', 'annotation-xml', 'maction', 'math', 'merror', 'mfenced', 'mfrac', 'mi', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mprescripts', 'mroot', 'mrow', 'mspace', 'msqrt', 'mstyle', 'msub', 'msubsup', 'msup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', - 'munderover', 'none', 'semantics'] + 'munderover', 'none', 'semantics']) - mathml_attributes = ['actiontype', 'align', 'columnalign', 'columnalign', + mathml_attributes = set(['actiontype', 'align', 'columnalign', 'columnalign', 'columnalign', 'close', 'columnlines', 'columnspacing', 'columnspan', 'depth', 'display', 'displaystyle', 'encoding', 'equalcolumns', 'equalrows', 'fence', 'fontstyle', 'fontweight', 'frame', 'height', 'linethickness', @@ -2561,18 +2671,18 @@ class _HTMLSanitizer(_BaseHTMLProcessor): 'maxsize', 'minsize', 'open', 'other', 'rowalign', 'rowalign', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'scriptlevel', 'selection', 'separator', 'separators', 'stretchy', 'width', 'width', 'xlink:href', - 'xlink:show', 'xlink:type', 'xmlns', 'xmlns:xlink'] + 'xlink:show', 'xlink:type', 'xmlns', 'xmlns:xlink']) # svgtiny - foreignObject + linearGradient + radialGradient + stop - svg_elements = ['a', 'animate', 'animateColor', 'animateMotion', + svg_elements = set(['a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle', 'defs', 'desc', 'ellipse', 'foreignObject', - 'font-face', 'font-face-name', 'font-face-src', 'g', 'glyph', 'hkern', + 'font-face', 'font-face-name', 'font-face-src', 'g', 'glyph', 'hkern', 'linearGradient', 'line', 'marker', 'metadata', 'missing-glyph', 'mpath', 'path', 'polygon', 'polyline', 'radialGradient', 'rect', 'set', 'stop', - 'svg', 'switch', 'text', 'title', 'tspan', 'use'] + 'svg', 'switch', 'text', 'title', 'tspan', 'use']) # svgtiny + class + opacity + offset + xmlns + xmlns:xlink - svg_attributes = ['accent-height', 'accumulate', 'additive', 'alphabetic', + svg_attributes = set(['accent-height', 'accumulate', 'additive', 'alphabetic', 'arabic-form', 'ascent', 'attributeName', 'attributeType', 'baseProfile', 'bbox', 'begin', 'by', 'calcMode', 'cap-height', 'class', 'color', 'color-rendering', 'content', 'cx', 'cy', 'd', 'dx', @@ -2598,21 +2708,21 @@ class _HTMLSanitizer(_BaseHTMLProcessor): 'widths', 'x', 'x-height', 'x1', 'x2', 'xlink:actuate', 'xlink:arcrole', 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type', 'xml:base', 'xml:lang', 'xml:space', 'xmlns', 'xmlns:xlink', 'y', 'y1', - 'y2', 'zoomAndPan'] + 'y2', 'zoomAndPan']) svg_attr_map = None svg_elem_map = None - acceptable_svg_properties = [ 'fill', 'fill-opacity', 'fill-rule', + acceptable_svg_properties = set([ 'fill', 'fill-opacity', 'fill-rule', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin', - 'stroke-opacity'] + 'stroke-opacity']) def reset(self): _BaseHTMLProcessor.reset(self) self.unacceptablestack = 0 self.mathmlOK = 0 self.svgOK = 0 - + def unknown_starttag(self, tag, attrs): acceptable_attributes = self.acceptable_attributes keymap = {} @@ -2666,21 +2776,27 @@ class _HTMLSanitizer(_BaseHTMLProcessor): for key, value in self.normalize_attrs(attrs): if key in acceptable_attributes: key=keymap.get(key,key) + # make sure the uri uses an acceptable uri scheme + if key == u'href': + value = _makeSafeAbsoluteURI(value) clean_attrs.append((key,value)) elif key=='style': clean_value = self.sanitize_style(value) - if clean_value: clean_attrs.append((key,clean_value)) + if clean_value: + clean_attrs.append((key,clean_value)) _BaseHTMLProcessor.unknown_starttag(self, tag, clean_attrs) - + def unknown_endtag(self, tag): if not tag in self.acceptable_elements: if tag in self.unacceptable_elements_with_end_tag: self.unacceptablestack -= 1 if self.mathmlOK and tag in self.mathml_elements: - if tag == 'math' and self.mathmlOK: self.mathmlOK -= 1 + if tag == 'math' and self.mathmlOK: + self.mathmlOK -= 1 elif self.svgOK and tag in self.svg_elements: tag = self.svg_elem_map.get(tag,tag) - if tag == 'svg' and self.svgOK: self.svgOK -= 1 + if tag == 'svg' and self.svgOK: + self.svgOK -= 1 else: return _BaseHTMLProcessor.unknown_endtag(self, tag) @@ -2700,29 +2816,46 @@ class _HTMLSanitizer(_BaseHTMLProcessor): style=re.compile('url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ',style) # gauntlet - if not re.match("""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): return '' + if not re.match("""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): + return '' # This replaced a regexp that used re.match and was prone to pathological back-tracking. - if re.sub("\s*[-\w]+\s*:\s*[^:;]*;?", '', style).strip(): return '' + if re.sub("\s*[-\w]+\s*:\s*[^:;]*;?", '', style).strip(): + return '' clean = [] for prop,value in re.findall("([-\w]+)\s*:\s*([^:;]*)",style): - if not value: continue - if prop.lower() in self.acceptable_css_properties: - clean.append(prop + ': ' + value + ';') - elif prop.split('-')[0].lower() in ['background','border','margin','padding']: - for keyword in value.split(): - if not keyword in self.acceptable_css_keywords and \ - not self.valid_css_values.match(keyword): - break - else: - clean.append(prop + ': ' + value + ';') - elif self.svgOK and prop.lower() in self.acceptable_svg_properties: - clean.append(prop + ': ' + value + ';') + if not value: + continue + if prop.lower() in self.acceptable_css_properties: + clean.append(prop + ': ' + value + ';') + elif prop.split('-')[0].lower() in ['background','border','margin','padding']: + for keyword in value.split(): + if not keyword in self.acceptable_css_keywords and \ + not self.valid_css_values.match(keyword): + break + else: + clean.append(prop + ': ' + value + ';') + elif self.svgOK and prop.lower() in self.acceptable_svg_properties: + clean.append(prop + ': ' + value + ';') return ' '.join(clean) + def parse_comment(self, i, report=1): + ret = _BaseHTMLProcessor.parse_comment(self, i, report) + if ret >= 0: + return ret + # if ret == -1, this may be a malicious attempt to circumvent + # sanitization, or a page-destroying unclosed comment + match = re.compile(r'--[^>]*>').search(self.rawdata, i+4) + if match: + return match.end() + # unclosed comment; deliberately fail to handle_data() + return len(self.rawdata) + def _sanitizeHTML(htmlSource, encoding, _type): + if not _SGML_AVAILABLE: + return htmlSource p = _HTMLSanitizer(encoding, _type) htmlSource = htmlSource.replace('<![CDATA[', '<![CDATA[') p.feed(htmlSource) @@ -2747,7 +2880,7 @@ def _sanitizeHTML(htmlSource, encoding, _type): except: pass if _tidy: - utf8 = type(data) == type(u'') + utf8 = isinstance(data, unicode) if utf8: data = data.encode('utf-8') data = _tidy(data, output_xhtml=1, numeric_entities=1, wrap=0, char_encoding="utf8") @@ -2764,39 +2897,29 @@ def _sanitizeHTML(htmlSource, encoding, _type): class _FeedURLHandler(urllib2.HTTPDigestAuthHandler, urllib2.HTTPRedirectHandler, urllib2.HTTPDefaultErrorHandler): def http_error_default(self, req, fp, code, msg, headers): - if ((code / 100) == 3) and (code != 304): - return self.http_error_302(req, fp, code, msg, headers) - infourl = urllib.addinfourl(fp, headers, req.get_full_url()) - infourl.status = code - return infourl - - def http_error_302(self, req, fp, code, msg, headers): - if headers.dict.has_key('location'): - infourl = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers) - else: - infourl = urllib.addinfourl(fp, headers, req.get_full_url()) - if not hasattr(infourl, 'status'): - infourl.status = code - return infourl - - def http_error_301(self, req, fp, code, msg, headers): - if headers.dict.has_key('location'): - infourl = urllib2.HTTPRedirectHandler.http_error_301(self, req, fp, code, msg, headers) - else: - infourl = urllib.addinfourl(fp, headers, req.get_full_url()) - if not hasattr(infourl, 'status'): - infourl.status = code - return infourl - - http_error_300 = http_error_302 - http_error_303 = http_error_302 - http_error_307 = http_error_302 - + # The default implementation just raises HTTPError. + # Forget that. + fp.status = code + return fp + + def http_error_301(self, req, fp, code, msg, hdrs): + result = urllib2.HTTPRedirectHandler.http_error_301(self, req, fp, + code, msg, hdrs) + result.status = code + result.newurl = result.geturl() + return result + # The default implementations in urllib2.HTTPRedirectHandler + # are identical, so hardcoding a http_error_301 call above + # won't affect anything + http_error_300 = http_error_301 + http_error_302 = http_error_301 + http_error_303 = http_error_301 + http_error_307 = http_error_301 + def http_error_401(self, req, fp, code, msg, headers): # Check if # - server requires digest auth, AND # - we tried (unsuccessfully) with basic auth, AND - # - we're using Python 2.3.3 or later (digest auth is irreparably broken in earlier versions) # If all conditions hold, parse authentication information # out of the Authorization header we sent the first time # (for the username and password) and the WWW-Authenticate @@ -2804,17 +2927,16 @@ class _FeedURLHandler(urllib2.HTTPDigestAuthHandler, urllib2.HTTPRedirectHandler # the request with the appropriate digest auth headers instead. # This evil genius hack has been brought to you by Aaron Swartz. host = urlparse.urlparse(req.get_full_url())[1] - try: - assert sys.version.split()[0] >= '2.3.3' - assert base64 is not None - user, passw = _base64decode(req.headers['Authorization'].split(' ')[1]).split(':') - realm = re.findall('realm="([^"]*)"', headers['WWW-Authenticate'])[0] - self.add_password(realm, host, user, passw) - retry = self.http_error_auth_reqed('www-authenticate', host, req, headers) - self.reset_retry_count() - return retry - except: + if base64 is None or 'Authorization' not in req.headers \ + or 'WWW-Authenticate' not in headers: return self.http_error_default(req, fp, code, msg, headers) + auth = _base64decode(req.headers['Authorization'].split(' ')[1]) + user, passw = auth.split(':') + realm = re.findall('realm="([^"]*)"', headers['WWW-Authenticate'])[0] + self.add_password(realm, host, user, passw) + retry = self.http_error_auth_reqed('www-authenticate', host, req, headers) + self.reset_retry_count() + return retry def _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, handlers, request_headers): """URL, filename, or string --> stream @@ -2851,10 +2973,8 @@ def _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, h if hasattr(url_file_stream_or_string, 'read'): return url_file_stream_or_string - if url_file_stream_or_string == '-': - return sys.stdin - - if urlparse.urlparse(url_file_stream_or_string)[0] in ('http', 'https', 'ftp', 'file', 'feed'): + if isinstance(url_file_stream_or_string, basestring) \ + and urlparse.urlparse(url_file_stream_or_string)[0] in ('http', 'https', 'ftp', 'file', 'feed'): # Deal with the feed URI scheme if url_file_stream_or_string.startswith('feed:http'): url_file_stream_or_string = url_file_stream_or_string[5:] @@ -2862,9 +2982,9 @@ def _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, h url_file_stream_or_string = 'http:' + url_file_stream_or_string[5:] if not agent: agent = USER_AGENT - # test for inline user:password for basic auth + # Test for inline user:password credentials for HTTP basic auth auth = None - if base64: + if base64 and not url_file_stream_or_string.startswith('ftp:'): urltype, rest = urllib.splittype(url_file_stream_or_string) realhost, rest = urllib.splithost(rest) if realhost: @@ -2874,38 +2994,66 @@ def _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, h auth = base64.standard_b64encode(user_passwd).strip() # iri support - try: - if isinstance(url_file_stream_or_string,unicode): - url_file_stream_or_string = url_file_stream_or_string.encode('idna').decode('utf-8') - else: - url_file_stream_or_string = url_file_stream_or_string.decode('utf-8').encode('idna').decode('utf-8') - except: - pass + if isinstance(url_file_stream_or_string, unicode): + url_file_stream_or_string = _convert_to_idn(url_file_stream_or_string) # try to open with urllib2 (to use optional headers) request = _build_urllib2_request(url_file_stream_or_string, agent, etag, modified, referrer, auth, request_headers) - opener = apply(urllib2.build_opener, tuple(handlers + [_FeedURLHandler()])) + opener = urllib2.build_opener(*tuple(handlers + [_FeedURLHandler()])) opener.addheaders = [] # RMK - must clear so we only send our custom User-Agent try: return opener.open(request) finally: opener.close() # JohnD - + # try to open with native open function (if url_file_stream_or_string is a filename) try: return open(url_file_stream_or_string, 'rb') - except: + except (IOError, UnicodeEncodeError, TypeError): + # if url_file_stream_or_string is a unicode object that + # cannot be converted to the encoding returned by + # sys.getfilesystemencoding(), a UnicodeEncodeError + # will be thrown + # If url_file_stream_or_string is a string that contains NULL + # (such as an XML document encoded in UTF-32), TypeError will + # be thrown. pass # treat url_file_stream_or_string as string - return _StringIO(str(url_file_stream_or_string)) + if isinstance(url_file_stream_or_string, unicode): + return _StringIO(url_file_stream_or_string.encode('utf-8')) + return _StringIO(url_file_stream_or_string) + +def _convert_to_idn(url): + """Convert a URL to IDN notation""" + # this function should only be called with a unicode string + # strategy: if the host cannot be encoded in ascii, then + # it'll be necessary to encode it in idn form + parts = list(urlparse.urlsplit(url)) + try: + parts[1].encode('ascii') + except UnicodeEncodeError: + # the url needs to be converted to idn notation + host = parts[1].rsplit(':', 1) + newhost = [] + port = u'' + if len(host) == 2: + port = host.pop() + for h in host[0].split('.'): + newhost.append(h.encode('idna').decode('utf-8')) + parts[1] = '.'.join(newhost) + if port: + parts[1] += ':' + port + return urlparse.urlunsplit(parts) + else: + return url def _build_urllib2_request(url, agent, etag, modified, referrer, auth, request_headers): request = urllib2.Request(url) request.add_header('User-Agent', agent) if etag: request.add_header('If-None-Match', etag) - if type(modified) == type(''): + if isinstance(modified, basestring): modified = _parse_date(modified) elif isinstance(modified, datetime.datetime): modified = modified.utctimetuple() @@ -2942,7 +3090,7 @@ _date_handlers = [] def registerDateHandler(func): '''Register a date handler function (takes string, returns 9-tuple date in GMT)''' _date_handlers.insert(0, func) - + # ISO-8601 date parsing routines written by Fazal Majid. # The ISO 8601 standard is very convoluted and irregular - a full ISO 8601 # parser is beyond the scope of feedparser and would be a worthwhile addition @@ -2953,7 +3101,7 @@ def registerDateHandler(func): # Please note the order in templates is significant because we need a # greedy match. _iso8601_tmpl = ['YYYY-?MM-?DD', 'YYYY-0MM?-?DD', 'YYYY-MM', 'YYYY-?OOO', - 'YY-?MM-?DD', 'YY-?OOO', 'YYYY', + 'YY-?MM-?DD', 'YY-?OOO', 'YYYY', '-YY-?MM', '-OOO', '-YY', '--MM-?DD', '--MM', '---DD', @@ -2985,9 +3133,12 @@ def _parse_date_iso8601(dateString): m = None for _iso8601_match in _iso8601_matches: m = _iso8601_match(dateString) - if m: break - if not m: return - if m.span() == (0, 0): return + if m: + break + if not m: + return + if m.span() == (0, 0): + return params = m.groupdict() ordinal = params.get('ordinal', 0) if ordinal: @@ -3025,7 +3176,7 @@ def _parse_date_iso8601(dateString): day = int(day) # special case of the century - is the first year of the 21st century # 2000 or 2001 ? The debate goes on... - if 'century' in params.keys(): + if 'century' in params: year = (int(params['century']) - 1) * 100 + 1 # in ISO 8601 most fields are optional for field in ['hour', 'minute', 'second', 'tzhour', 'tzmin']: @@ -3055,7 +3206,7 @@ def _parse_date_iso8601(dateString): # Many implementations have bugs, but we'll pretend they don't. return time.localtime(time.mktime(tuple(tm))) registerDateHandler(_parse_date_iso8601) - + # 8-bit date handling routines written by ytrewq1. _korean_year = u'\ub144' # b3e2 in euc-kr _korean_month = u'\uc6d4' # bff9 in euc-kr @@ -3072,19 +3223,20 @@ _korean_nate_date_re = \ def _parse_date_onblog(dateString): '''Parse a string according to the OnBlog 8-bit date format''' m = _korean_onblog_date_re.match(dateString) - if not m: return + if not m: + return w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ 'hour': m.group(4), 'minute': m.group(5), 'second': m.group(6),\ 'zonediff': '+09:00'} - if _debug: sys.stderr.write('OnBlog date parsed as: %s\n' % w3dtfdate) return _parse_date_w3dtf(w3dtfdate) registerDateHandler(_parse_date_onblog) def _parse_date_nate(dateString): '''Parse a string according to the Nate 8-bit date format''' m = _korean_nate_date_re.match(dateString) - if not m: return + if not m: + return hour = int(m.group(5)) ampm = m.group(4) if (ampm == _korean_pm): @@ -3096,24 +3248,9 @@ def _parse_date_nate(dateString): {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ 'hour': hour, 'minute': m.group(6), 'second': m.group(7),\ 'zonediff': '+09:00'} - if _debug: sys.stderr.write('Nate date parsed as: %s\n' % w3dtfdate) return _parse_date_w3dtf(w3dtfdate) registerDateHandler(_parse_date_nate) -_mssql_date_re = \ - re.compile('(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})(\.\d+)?') -def _parse_date_mssql(dateString): - '''Parse a string according to the MS SQL date format''' - m = _mssql_date_re.match(dateString) - if not m: return - w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ - {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ - 'hour': m.group(4), 'minute': m.group(5), 'second': m.group(6),\ - 'zonediff': '+09:00'} - if _debug: sys.stderr.write('MS SQL date parsed as: %s\n' % w3dtfdate) - return _parse_date_w3dtf(w3dtfdate) -registerDateHandler(_parse_date_mssql) - # Unicode strings for Greek date strings _greek_months = \ { \ @@ -3146,7 +3283,7 @@ _greek_wdays = \ u'\u03a4\u03b5\u03c4': u'Wed', # d4e5f4 in iso-8859-7 u'\u03a0\u03b5\u03bc': u'Thu', # d0e5ec in iso-8859-7 u'\u03a0\u03b1\u03c1': u'Fri', # d0e1f1 in iso-8859-7 - u'\u03a3\u03b1\u03b2': u'Sat', # d3e1e2 in iso-8859-7 + u'\u03a3\u03b1\u03b2': u'Sat', # d3e1e2 in iso-8859-7 } _greek_date_format_re = \ @@ -3155,17 +3292,14 @@ _greek_date_format_re = \ def _parse_date_greek(dateString): '''Parse a string according to a Greek 8-bit date format.''' m = _greek_date_format_re.match(dateString) - if not m: return - try: - wday = _greek_wdays[m.group(1)] - month = _greek_months[m.group(3)] - except: + if not m: return + wday = _greek_wdays[m.group(1)] + month = _greek_months[m.group(3)] rfc822date = '%(wday)s, %(day)s %(month)s %(year)s %(hour)s:%(minute)s:%(second)s %(zonediff)s' % \ {'wday': wday, 'day': m.group(2), 'month': month, 'year': m.group(4),\ 'hour': m.group(5), 'minute': m.group(6), 'second': m.group(7),\ 'zonediff': m.group(8)} - if _debug: sys.stderr.write('Greek date parsed as: %s\n' % rfc822date) return _parse_date_rfc822(rfc822date) registerDateHandler(_parse_date_greek) @@ -3192,22 +3326,19 @@ _hungarian_date_format_re = \ def _parse_date_hungarian(dateString): '''Parse a string according to a Hungarian 8-bit date format.''' m = _hungarian_date_format_re.match(dateString) - if not m: return - try: - month = _hungarian_months[m.group(2)] - day = m.group(3) - if len(day) == 1: - day = '0' + day - hour = m.group(4) - if len(hour) == 1: - hour = '0' + hour - except: - return + if not m or m.group(2) not in _hungarian_months: + return None + month = _hungarian_months[m.group(2)] + day = m.group(3) + if len(day) == 1: + day = '0' + day + hour = m.group(4) + if len(hour) == 1: + hour = '0' + hour w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s%(zonediff)s' % \ {'year': m.group(1), 'month': month, 'day': day,\ 'hour': hour, 'minute': m.group(5),\ 'zonediff': m.group(6)} - if _debug: sys.stderr.write('Hungarian date parsed as: %s\n' % w3dtfdate) return _parse_date_w3dtf(w3dtfdate) registerDateHandler(_parse_date_hungarian) @@ -3215,6 +3346,9 @@ registerDateHandler(_parse_date_hungarian) # Drake and licensed under the Python license. Removed all range checking # for month, day, hour, minute, and second, since mktime will normalize # these later +# Modified to also support MSSQL-style datetimes as defined at: +# http://msdn.microsoft.com/en-us/library/ms186724.aspx +# (which basically means allowing a space as a date/time/timezone separator) def _parse_date_w3dtf(dateString): def __extract_date(m): year = int(m.group('year')) @@ -3240,7 +3374,7 @@ def _parse_date_w3dtf(dateString): day = 31 elif jday < julian: if day + diff < 28: - day = day + diff + day = day + diff else: month = month + 1 return year, month, day @@ -3296,315 +3430,455 @@ def _parse_date_w3dtf(dateString): '(?:(?P<dsep>-|)' '(?:(?P<month>\d\d)(?:(?P=dsep)(?P<day>\d\d))?' '|(?P<julian>\d\d\d)))?') - __tzd_re = '(?P<tzd>[-+](?P<tzdhours>\d\d)(?::?(?P<tzdminutes>\d\d))|Z)' - __tzd_rx = re.compile(__tzd_re) + __tzd_re = ' ?(?P<tzd>[-+](?P<tzdhours>\d\d)(?::?(?P<tzdminutes>\d\d))|Z)?' __time_re = ('(?P<hours>\d\d)(?P<tsep>:|)(?P<minutes>\d\d)' '(?:(?P=tsep)(?P<seconds>\d\d)(?:[.,]\d+)?)?' + __tzd_re) - __datetime_re = '%s(?:T%s)?' % (__date_re, __time_re) + __datetime_re = '%s(?:[T ]%s)?' % (__date_re, __time_re) __datetime_rx = re.compile(__datetime_re) m = __datetime_rx.match(dateString) - if (m is None) or (m.group() != dateString): return + if (m is None) or (m.group() != dateString): + return gmt = __extract_date(m) + __extract_time(m) + (0, 0, 0) - if gmt[0] == 0: return + if gmt[0] == 0: + return return time.gmtime(time.mktime(gmt) + __extract_tzd(m) - time.timezone) registerDateHandler(_parse_date_w3dtf) -def _parse_date_rfc822(dateString): - '''Parse an RFC822, RFC1123, RFC2822, or asctime-style date''' - data = dateString.split() - if data[0][-1] in (',', '.') or data[0].lower() in rfc822._daynames: - del data[0] - if len(data) == 4: - s = data[3] - i = s.find('+') - if i > 0: - data[3:] = [s[:i], s[i+1:]] - else: - data.append('') - dateString = " ".join(data) - # Account for the Etc/GMT timezone by stripping 'Etc/' - elif len(data) == 5 and data[4].lower().startswith('etc/'): - data[4] = data[4][4:] - dateString = " ".join(data) - if len(data) < 5: - dateString += ' 00:00:00 GMT' +# Define the strings used by the RFC822 datetime parser +_rfc822_months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', + 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'] +_rfc822_daynames = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] + +# Only the first three letters of the month name matter +_rfc822_month = "(?P<month>%s)(?:[a-z]*,?)" % ('|'.join(_rfc822_months)) +# The year may be 2 or 4 digits; capture the century if it exists +_rfc822_year = "(?P<year>(?:\d{2})?\d{2})" +_rfc822_day = "(?P<day> *\d{1,2})" +_rfc822_date = "%s %s %s" % (_rfc822_day, _rfc822_month, _rfc822_year) + +_rfc822_hour = "(?P<hour>\d{2}):(?P<minute>\d{2})(?::(?P<second>\d{2}))?" +_rfc822_tz = "(?P<tz>ut|gmt(?:[+-]\d{2}:\d{2})?|[aecmp][sd]?t|[zamny]|[+-]\d{4})" +_rfc822_tznames = { + 'ut': 0, 'gmt': 0, 'z': 0, + 'adt': -3, 'ast': -4, 'at': -4, + 'edt': -4, 'est': -5, 'et': -5, + 'cdt': -5, 'cst': -6, 'ct': -6, + 'mdt': -6, 'mst': -7, 'mt': -7, + 'pdt': -7, 'pst': -8, 'pt': -8, + 'a': -1, 'n': 1, + 'm': -12, 'y': 12, + } +# The timezone may be prefixed by 'Etc/' +_rfc822_time = "%s (?:etc/)?%s" % (_rfc822_hour, _rfc822_tz) + +_rfc822_dayname = "(?P<dayname>%s)" % ('|'.join(_rfc822_daynames)) +_rfc822_match = re.compile( + "(?:%s, )?%s(?: %s)?" % (_rfc822_dayname, _rfc822_date, _rfc822_time) +).match + +def _parse_date_group_rfc822(m): + # Calculate a date and timestamp + for k in ('year', 'day', 'hour', 'minute', 'second'): + m[k] = int(m[k]) + m['month'] = _rfc822_months.index(m['month']) + 1 + # If the year is 2 digits, assume everything in the 90's is the 1990's + if m['year'] < 100: + m['year'] += (1900, 2000)[m['year'] < 90] + stamp = datetime.datetime(*[m[i] for i in + ('year', 'month', 'day', 'hour', 'minute', 'second')]) + + # Use the timezone information to calculate the difference between + # the given date and timestamp and Universal Coordinated Time + tzhour = 0 + tzmin = 0 + if m['tz'] and m['tz'].startswith('gmt'): + # Handle GMT and GMT+hh:mm timezone syntax (the trailing + # timezone info will be handled by the next `if` block) + m['tz'] = ''.join(m['tz'][3:].split(':')) or 'gmt' + if not m['tz']: + pass + elif m['tz'].startswith('+'): + tzhour = int(m['tz'][1:3]) + tzmin = int(m['tz'][3:]) + elif m['tz'].startswith('-'): + tzhour = int(m['tz'][1:3]) * -1 + tzmin = int(m['tz'][3:]) * -1 + else: + tzhour = _rfc822_tznames[m['tz']] + delta = datetime.timedelta(0, 0, 0, 0, tzmin, tzhour) + + # Return the date and timestamp in UTC + return (stamp - delta).utctimetuple() + +def _parse_date_rfc822(dt): + """Parse RFC 822 dates and times, with one minor + difference: years may be 4DIGIT or 2DIGIT. + http://tools.ietf.org/html/rfc822#section-5""" + try: + m = _rfc822_match(dt.lower()).groupdict(0) + except AttributeError: + return None + + return _parse_date_group_rfc822(m) +registerDateHandler(_parse_date_rfc822) + +def _parse_date_rfc822_grubby(dt): + """Parse date format similar to RFC 822, but + the comma after the dayname is optional and + month/day are inverted""" + _rfc822_date_grubby = "%s %s %s" % (_rfc822_month, _rfc822_day, _rfc822_year) + _rfc822_match_grubby = re.compile( + "(?:%s[,]? )?%s(?: %s)?" % (_rfc822_dayname, _rfc822_date_grubby, _rfc822_time) + ).match + + try: + m = _rfc822_match_grubby(dt.lower()).groupdict(0) + except AttributeError: + return None + + return _parse_date_group_rfc822(m) +registerDateHandler(_parse_date_rfc822_grubby) + +def _parse_date_asctime(dt): + """Parse asctime-style dates""" + dayname, month, day, remainder = dt.split(None, 3) + # Convert month and day into zero-padded integers + month = '%02i ' % (_rfc822_months.index(month.lower()) + 1) + day = '%02i ' % (int(day),) + dt = month + day + remainder + return time.strptime(dt, '%m %d %H:%M:%S %Y')[:-1] + (0, ) +registerDateHandler(_parse_date_asctime) + +def _parse_date_perforce(aDateString): + """parse a date in yyyy/mm/dd hh:mm:ss TTT format""" + # Fri, 2006/09/15 08:19:53 EDT + _my_date_pattern = re.compile( \ + r'(\w{,3}), (\d{,4})/(\d{,2})/(\d{2}) (\d{,2}):(\d{2}):(\d{2}) (\w{,3})') + + m = _my_date_pattern.search(aDateString) + if m is None: + return None + dow, year, month, day, hour, minute, second, tz = m.groups() + months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + dateString = "%s, %s %s %s %s:%s:%s %s" % (dow, day, months[int(month) - 1], year, hour, minute, second, tz) tm = rfc822.parsedate_tz(dateString) if tm: return time.gmtime(rfc822.mktime_tz(tm)) -# rfc822.py defines several time zones, but we define some extra ones. -# 'ET' is equivalent to 'EST', etc. -_additional_timezones = {'AT': -400, 'ET': -500, 'CT': -600, 'MT': -700, 'PT': -800} -rfc822._timezones.update(_additional_timezones) -registerDateHandler(_parse_date_rfc822) - -def _parse_date_perforce(aDateString): - """parse a date in yyyy/mm/dd hh:mm:ss TTT format""" - # Fri, 2006/09/15 08:19:53 EDT - _my_date_pattern = re.compile( \ - r'(\w{,3}), (\d{,4})/(\d{,2})/(\d{2}) (\d{,2}):(\d{2}):(\d{2}) (\w{,3})') - - dow, year, month, day, hour, minute, second, tz = \ - _my_date_pattern.search(aDateString).groups() - months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - dateString = "%s, %s %s %s %s:%s:%s %s" % (dow, day, months[int(month) - 1], year, hour, minute, second, tz) - tm = rfc822.parsedate_tz(dateString) - if tm: - return time.gmtime(rfc822.mktime_tz(tm)) registerDateHandler(_parse_date_perforce) def _parse_date(dateString): '''Parses a variety of date formats into a 9-tuple in GMT''' + if not dateString: + return None for handler in _date_handlers: try: date9tuple = handler(dateString) - if not date9tuple: continue - if len(date9tuple) != 9: - if _debug: sys.stderr.write('date handler function must return 9-tuple\n') - raise ValueError - map(int, date9tuple) - return date9tuple - except Exception, e: - if _debug: sys.stderr.write('%s raised %s\n' % (handler.__name__, repr(e))) - pass + except (KeyError, OverflowError, ValueError): + continue + if not date9tuple: + continue + if len(date9tuple) != 9: + continue + return date9tuple return None -def _getCharacterEncoding(http_headers, xml_data): - '''Get the character encoding of the XML document +# Each marker represents some of the characters of the opening XML +# processing instruction ('<?xm') in the specified encoding. +EBCDIC_MARKER = _l2bytes([0x4C, 0x6F, 0xA7, 0x94]) +UTF16BE_MARKER = _l2bytes([0x00, 0x3C, 0x00, 0x3F]) +UTF16LE_MARKER = _l2bytes([0x3C, 0x00, 0x3F, 0x00]) +UTF32BE_MARKER = _l2bytes([0x00, 0x00, 0x00, 0x3C]) +UTF32LE_MARKER = _l2bytes([0x3C, 0x00, 0x00, 0x00]) + +ZERO_BYTES = _l2bytes([0x00, 0x00]) + +# Match the opening XML declaration. +# Example: <?xml version="1.0" encoding="utf-8"?> +RE_XML_DECLARATION = re.compile('^<\?xml[^>]*?>') + +# Capture the value of the XML processing instruction's encoding attribute. +# Example: <?xml version="1.0" encoding="utf-8"?> +RE_XML_PI_ENCODING = re.compile(_s2bytes('^<\?.*encoding=[\'"](.*?)[\'"].*\?>')) + +def convert_to_utf8(http_headers, data): + '''Detect and convert the character encoding to UTF-8. http_headers is a dictionary - xml_data is a raw string (not Unicode) - - This is so much trickier than it sounds, it's not even funny. - According to RFC 3023 ('XML Media Types'), if the HTTP Content-Type - is application/xml, application/*+xml, - application/xml-external-parsed-entity, or application/xml-dtd, - the encoding given in the charset parameter of the HTTP Content-Type - takes precedence over the encoding given in the XML prefix within the - document, and defaults to 'utf-8' if neither are specified. But, if - the HTTP Content-Type is text/xml, text/*+xml, or - text/xml-external-parsed-entity, the encoding given in the XML prefix - within the document is ALWAYS IGNORED and only the encoding given in - the charset parameter of the HTTP Content-Type header should be - respected, and it defaults to 'us-ascii' if not specified. - - Furthermore, discussion on the atom-syntax mailing list with the - author of RFC 3023 leads me to the conclusion that any document - served with a Content-Type of text/* and no charset parameter - must be treated as us-ascii. (We now do this.) And also that it - must always be flagged as non-well-formed. (We now do this too.) - - If Content-Type is unspecified (input was local file or non-HTTP source) - or unrecognized (server just got it totally wrong), then go by the - encoding given in the XML prefix of the document and default to - 'iso-8859-1' as per the HTTP specification (RFC 2616). - - Then, assuming we didn't find a character encoding in the HTTP headers - (and the HTTP Content-type allowed us to look in the body), we need - to sniff the first few bytes of the XML data and try to determine - whether the encoding is ASCII-compatible. Section F of the XML - specification shows the way here: - http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info - - If the sniffed encoding is not ASCII-compatible, we need to make it - ASCII compatible so that we can sniff further into the XML declaration - to find the encoding attribute, which will tell us the true encoding. - - Of course, none of this guarantees that we will be able to parse the - feed in the declared character encoding (assuming it was declared - correctly, which many are not). CJKCodecs and iconv_codec help a lot; - you should definitely install them if you can. - http://cjkpython.i18n.org/ - ''' + data is a raw string (not Unicode)''' + + # This is so much trickier than it sounds, it's not even funny. + # According to RFC 3023 ('XML Media Types'), if the HTTP Content-Type + # is application/xml, application/*+xml, + # application/xml-external-parsed-entity, or application/xml-dtd, + # the encoding given in the charset parameter of the HTTP Content-Type + # takes precedence over the encoding given in the XML prefix within the + # document, and defaults to 'utf-8' if neither are specified. But, if + # the HTTP Content-Type is text/xml, text/*+xml, or + # text/xml-external-parsed-entity, the encoding given in the XML prefix + # within the document is ALWAYS IGNORED and only the encoding given in + # the charset parameter of the HTTP Content-Type header should be + # respected, and it defaults to 'us-ascii' if not specified. + + # Furthermore, discussion on the atom-syntax mailing list with the + # author of RFC 3023 leads me to the conclusion that any document + # served with a Content-Type of text/* and no charset parameter + # must be treated as us-ascii. (We now do this.) And also that it + # must always be flagged as non-well-formed. (We now do this too.) + + # If Content-Type is unspecified (input was local file or non-HTTP source) + # or unrecognized (server just got it totally wrong), then go by the + # encoding given in the XML prefix of the document and default to + # 'iso-8859-1' as per the HTTP specification (RFC 2616). + + # Then, assuming we didn't find a character encoding in the HTTP headers + # (and the HTTP Content-type allowed us to look in the body), we need + # to sniff the first few bytes of the XML data and try to determine + # whether the encoding is ASCII-compatible. Section F of the XML + # specification shows the way here: + # http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info - def _parseHTTPContentType(content_type): - '''takes HTTP Content-Type header and returns (content type, charset) - - If no charset is specified, returns (content type, '') - If no content type is specified, returns ('', '') - Both return parameters are guaranteed to be lowercase strings - ''' - content_type = content_type or '' - content_type, params = cgi.parse_header(content_type) - return content_type, params.get('charset', '').replace("'", '') - - sniffed_xml_encoding = '' - xml_encoding = '' - true_encoding = '' - http_content_type, http_encoding = _parseHTTPContentType(http_headers.get('content-type', http_headers.get('Content-type'))) - # Must sniff for non-ASCII-compatible character encodings before - # searching for XML declaration. This heuristic is defined in - # section F of the XML specification: + # If the sniffed encoding is not ASCII-compatible, we need to make it + # ASCII compatible so that we can sniff further into the XML declaration + # to find the encoding attribute, which will tell us the true encoding. + + # Of course, none of this guarantees that we will be able to parse the + # feed in the declared character encoding (assuming it was declared + # correctly, which many are not). iconv_codec can help a lot; + # you should definitely install it if you can. + # http://cjkpython.i18n.org/ + + bom_encoding = u'' + xml_encoding = u'' + rfc3023_encoding = u'' + + # Look at the first few bytes of the document to guess what + # its encoding may be. We only need to decode enough of the + # document that we can use an ASCII-compatible regular + # expression to search for an XML encoding declaration. + # The heuristic follows the XML specification, section F: # http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info + # Check for BOMs first. + if data[:4] == codecs.BOM_UTF32_BE: + bom_encoding = u'utf-32be' + data = data[4:] + elif data[:4] == codecs.BOM_UTF32_LE: + bom_encoding = u'utf-32le' + data = data[4:] + elif data[:2] == codecs.BOM_UTF16_BE and data[2:4] != ZERO_BYTES: + bom_encoding = u'utf-16be' + data = data[2:] + elif data[:2] == codecs.BOM_UTF16_LE and data[2:4] != ZERO_BYTES: + bom_encoding = u'utf-16le' + data = data[2:] + elif data[:3] == codecs.BOM_UTF8: + bom_encoding = u'utf-8' + data = data[3:] + # Check for the characters '<?xm' in several encodings. + elif data[:4] == EBCDIC_MARKER: + bom_encoding = u'cp037' + elif data[:4] == UTF16BE_MARKER: + bom_encoding = u'utf-16be' + elif data[:4] == UTF16LE_MARKER: + bom_encoding = u'utf-16le' + elif data[:4] == UTF32BE_MARKER: + bom_encoding = u'utf-32be' + elif data[:4] == UTF32LE_MARKER: + bom_encoding = u'utf-32le' + + tempdata = data try: - if xml_data[:4] == _l2bytes([0x4c, 0x6f, 0xa7, 0x94]): - # EBCDIC - xml_data = _ebcdic_to_ascii(xml_data) - elif xml_data[:4] == _l2bytes([0x00, 0x3c, 0x00, 0x3f]): - # UTF-16BE - sniffed_xml_encoding = 'utf-16be' - xml_data = unicode(xml_data, 'utf-16be').encode('utf-8') - elif (len(xml_data) >= 4) and (xml_data[:2] == _l2bytes([0xfe, 0xff])) and (xml_data[2:4] != _l2bytes([0x00, 0x00])): - # UTF-16BE with BOM - sniffed_xml_encoding = 'utf-16be' - xml_data = unicode(xml_data[2:], 'utf-16be').encode('utf-8') - elif xml_data[:4] == _l2bytes([0x3c, 0x00, 0x3f, 0x00]): - # UTF-16LE - sniffed_xml_encoding = 'utf-16le' - xml_data = unicode(xml_data, 'utf-16le').encode('utf-8') - elif (len(xml_data) >= 4) and (xml_data[:2] == _l2bytes([0xff, 0xfe])) and (xml_data[2:4] != _l2bytes([0x00, 0x00])): - # UTF-16LE with BOM - sniffed_xml_encoding = 'utf-16le' - xml_data = unicode(xml_data[2:], 'utf-16le').encode('utf-8') - elif xml_data[:4] == _l2bytes([0x00, 0x00, 0x00, 0x3c]): - # UTF-32BE - sniffed_xml_encoding = 'utf-32be' - xml_data = unicode(xml_data, 'utf-32be').encode('utf-8') - elif xml_data[:4] == _l2bytes([0x3c, 0x00, 0x00, 0x00]): - # UTF-32LE - sniffed_xml_encoding = 'utf-32le' - xml_data = unicode(xml_data, 'utf-32le').encode('utf-8') - elif xml_data[:4] == _l2bytes([0x00, 0x00, 0xfe, 0xff]): - # UTF-32BE with BOM - sniffed_xml_encoding = 'utf-32be' - xml_data = unicode(xml_data[4:], 'utf-32be').encode('utf-8') - elif xml_data[:4] == _l2bytes([0xff, 0xfe, 0x00, 0x00]): - # UTF-32LE with BOM - sniffed_xml_encoding = 'utf-32le' - xml_data = unicode(xml_data[4:], 'utf-32le').encode('utf-8') - elif xml_data[:3] == _l2bytes([0xef, 0xbb, 0xbf]): - # UTF-8 with BOM - sniffed_xml_encoding = 'utf-8' - xml_data = unicode(xml_data[3:], 'utf-8').encode('utf-8') - else: - # ASCII-compatible - pass - xml_encoding_match = re.compile(_s2bytes('^<\?.*encoding=[\'"](.*?)[\'"].*\?>')).match(xml_data) - except: + if bom_encoding: + tempdata = data.decode(bom_encoding).encode('utf-8') + except (UnicodeDecodeError, LookupError): + # feedparser recognizes UTF-32 encodings that aren't + # available in Python 2.4 and 2.5, so it's possible to + # encounter a LookupError during decoding. xml_encoding_match = None + else: + xml_encoding_match = RE_XML_PI_ENCODING.match(tempdata) + if xml_encoding_match: xml_encoding = xml_encoding_match.groups()[0].decode('utf-8').lower() - if sniffed_xml_encoding and (xml_encoding in ('iso-10646-ucs-2', 'ucs-2', 'csunicode', 'iso-10646-ucs-4', 'ucs-4', 'csucs4', 'utf-16', 'utf-32', 'utf_16', 'utf_32', 'utf16', 'u16')): - xml_encoding = sniffed_xml_encoding + # Normalize the xml_encoding if necessary. + if bom_encoding and (xml_encoding in ( + u'u16', u'utf-16', u'utf16', u'utf_16', + u'u32', u'utf-32', u'utf32', u'utf_32', + u'iso-10646-ucs-2', u'iso-10646-ucs-4', + u'csucs4', u'csunicode', u'ucs-2', u'ucs-4' + )): + xml_encoding = bom_encoding + + # Find the HTTP Content-Type and, hopefully, a character + # encoding provided by the server. The Content-Type is used + # to choose the "correct" encoding among the BOM encoding, + # XML declaration encoding, and HTTP encoding, following the + # heuristic defined in RFC 3023. + http_content_type = http_headers.get('content-type') or '' + http_content_type, params = cgi.parse_header(http_content_type) + http_encoding = params.get('charset', '').replace("'", "") + if not isinstance(http_encoding, unicode): + http_encoding = http_encoding.decode('utf-8', 'ignore') + acceptable_content_type = 0 - application_content_types = ('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity') - text_content_types = ('text/xml', 'text/xml-external-parsed-entity') + application_content_types = (u'application/xml', u'application/xml-dtd', + u'application/xml-external-parsed-entity') + text_content_types = (u'text/xml', u'text/xml-external-parsed-entity') if (http_content_type in application_content_types) or \ - (http_content_type.startswith('application/') and http_content_type.endswith('+xml')): + (http_content_type.startswith(u'application/') and + http_content_type.endswith(u'+xml')): acceptable_content_type = 1 - true_encoding = http_encoding or xml_encoding or 'utf-8' + rfc3023_encoding = http_encoding or xml_encoding or u'utf-8' elif (http_content_type in text_content_types) or \ - (http_content_type.startswith('text/')) and http_content_type.endswith('+xml'): + (http_content_type.startswith(u'text/') and + http_content_type.endswith(u'+xml')): acceptable_content_type = 1 - true_encoding = http_encoding or 'us-ascii' - elif http_content_type.startswith('text/'): - true_encoding = http_encoding or 'us-ascii' - elif http_headers and (not (http_headers.has_key('content-type') or http_headers.has_key('Content-type'))): - true_encoding = xml_encoding or 'iso-8859-1' - else: - true_encoding = xml_encoding or 'utf-8' - # some feeds claim to be gb2312 but are actually gb18030. - # apparently MSIE and Firefox both do the following switch: - if true_encoding.lower() == 'gb2312': - true_encoding = 'gb18030' - return true_encoding, http_encoding, xml_encoding, sniffed_xml_encoding, acceptable_content_type - -def _toUTF8(data, encoding): - '''Changes an XML data stream on the fly to specify a new encoding - - data is a raw sequence of bytes (not Unicode) that is presumed to be in %encoding already - encoding is a string recognized by encodings.aliases - ''' - if _debug: sys.stderr.write('entering _toUTF8, trying encoding %s\n' % encoding) - # strip Byte Order Mark (if present) - if (len(data) >= 4) and (data[:2] == _l2bytes([0xfe, 0xff])) and (data[2:4] != _l2bytes([0x00, 0x00])): - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-16be': - sys.stderr.write('trying utf-16be instead\n') - encoding = 'utf-16be' - data = data[2:] - elif (len(data) >= 4) and (data[:2] == _l2bytes([0xff, 0xfe])) and (data[2:4] != _l2bytes([0x00, 0x00])): - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-16le': - sys.stderr.write('trying utf-16le instead\n') - encoding = 'utf-16le' - data = data[2:] - elif data[:3] == _l2bytes([0xef, 0xbb, 0xbf]): - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-8': - sys.stderr.write('trying utf-8 instead\n') - encoding = 'utf-8' - data = data[3:] - elif data[:4] == _l2bytes([0x00, 0x00, 0xfe, 0xff]): - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-32be': - sys.stderr.write('trying utf-32be instead\n') - encoding = 'utf-32be' - data = data[4:] - elif data[:4] == _l2bytes([0xff, 0xfe, 0x00, 0x00]): - if _debug: - sys.stderr.write('stripping BOM\n') - if encoding != 'utf-32le': - sys.stderr.write('trying utf-32le instead\n') - encoding = 'utf-32le' - data = data[4:] - newdata = unicode(data, encoding) - if _debug: sys.stderr.write('successfully converted %s data to unicode\n' % encoding) - declmatch = re.compile('^<\?xml[^>]*?>') - newdecl = '''<?xml version='1.0' encoding='utf-8'?>''' - if declmatch.search(newdata): - newdata = declmatch.sub(newdecl, newdata) + rfc3023_encoding = http_encoding or u'us-ascii' + elif http_content_type.startswith(u'text/'): + rfc3023_encoding = http_encoding or u'us-ascii' + elif http_headers and 'content-type' not in http_headers: + rfc3023_encoding = xml_encoding or u'iso-8859-1' else: - newdata = newdecl + u'\n' + newdata - return newdata.encode('utf-8') + rfc3023_encoding = xml_encoding or u'utf-8' + # gb18030 is a superset of gb2312, so always replace gb2312 + # with gb18030 for greater compatibility. + if rfc3023_encoding.lower() == u'gb2312': + rfc3023_encoding = u'gb18030' + if xml_encoding.lower() == u'gb2312': + xml_encoding = u'gb18030' + + # there are four encodings to keep track of: + # - http_encoding is the encoding declared in the Content-Type HTTP header + # - xml_encoding is the encoding declared in the <?xml declaration + # - bom_encoding is the encoding sniffed from the first 4 bytes of the XML data + # - rfc3023_encoding is the actual encoding, as per RFC 3023 and a variety of other conflicting specifications + error = None -def _stripDoctype(data): - '''Strips DOCTYPE from XML document, returns (rss_version, stripped_data) + if http_headers and (not acceptable_content_type): + if 'content-type' in http_headers: + msg = '%s is not an XML media type' % http_headers['content-type'] + else: + msg = 'no Content-type specified' + error = NonXMLContentType(msg) + + # determine character encoding + known_encoding = 0 + chardet_encoding = None + tried_encodings = [] + if chardet: + chardet_encoding = unicode(chardet.detect(data)['encoding'] or '', 'ascii', 'ignore') + # try: HTTP encoding, declared XML encoding, encoding sniffed from BOM + for proposed_encoding in (rfc3023_encoding, xml_encoding, bom_encoding, + chardet_encoding, u'utf-8', u'windows-1252', u'iso-8859-2'): + if not proposed_encoding: + continue + if proposed_encoding in tried_encodings: + continue + tried_encodings.append(proposed_encoding) + try: + data = data.decode(proposed_encoding) + except (UnicodeDecodeError, LookupError): + pass + else: + known_encoding = 1 + # Update the encoding in the opening XML processing instruction. + new_declaration = '''<?xml version='1.0' encoding='utf-8'?>''' + if RE_XML_DECLARATION.search(data): + data = RE_XML_DECLARATION.sub(new_declaration, data) + else: + data = new_declaration + u'\n' + data + data = data.encode('utf-8') + break + # if still no luck, give up + if not known_encoding: + error = CharacterEncodingUnknown( + 'document encoding unknown, I tried ' + + '%s, %s, utf-8, windows-1252, and iso-8859-2 but nothing worked' % + (rfc3023_encoding, xml_encoding)) + rfc3023_encoding = u'' + elif proposed_encoding != rfc3023_encoding: + error = CharacterEncodingOverride( + 'document declared as %s, but parsed as %s' % + (rfc3023_encoding, proposed_encoding)) + rfc3023_encoding = proposed_encoding + + return data, rfc3023_encoding, error + +# Match XML entity declarations. +# Example: <!ENTITY copyright "(C)"> +RE_ENTITY_PATTERN = re.compile(_s2bytes(r'^\s*<!ENTITY([^>]*?)>'), re.MULTILINE) + +# Match XML DOCTYPE declarations. +# Example: <!DOCTYPE feed [ ]> +RE_DOCTYPE_PATTERN = re.compile(_s2bytes(r'^\s*<!DOCTYPE([^>]*?)>'), re.MULTILINE) + +# Match safe entity declarations. +# This will allow hexadecimal character references through, +# as well as text, but not arbitrary nested entities. +# Example: cubed "³" +# Example: copyright "(C)" +# Forbidden: explode1 "&explode2;&explode2;" +RE_SAFE_ENTITY_PATTERN = re.compile(_s2bytes('\s+(\w+)\s+"(&#\w+;|[^&"]*)"')) + +def replace_doctype(data): + '''Strips and replaces the DOCTYPE, returns (rss_version, stripped_data) rss_version may be 'rss091n' or None - stripped_data is the same XML document, minus the DOCTYPE + stripped_data is the same XML document with a replaced DOCTYPE ''' + + # Divide the document into two groups by finding the location + # of the first element that doesn't begin with '<?' or '<!'. start = re.search(_s2bytes('<\w'), data) start = start and start.start() or -1 - head,data = data[:start+1], data[start+1:] - - entity_pattern = re.compile(_s2bytes(r'^\s*<!ENTITY([^>]*?)>'), re.MULTILINE) - entity_results=entity_pattern.findall(head) - head = entity_pattern.sub(_s2bytes(''), head) - doctype_pattern = re.compile(_s2bytes(r'^\s*<!DOCTYPE([^>]*?)>'), re.MULTILINE) - doctype_results = doctype_pattern.findall(head) + head, data = data[:start+1], data[start+1:] + + # Save and then remove all of the ENTITY declarations. + entity_results = RE_ENTITY_PATTERN.findall(head) + head = RE_ENTITY_PATTERN.sub(_s2bytes(''), head) + + # Find the DOCTYPE declaration and check the feed type. + doctype_results = RE_DOCTYPE_PATTERN.findall(head) doctype = doctype_results and doctype_results[0] or _s2bytes('') - if doctype.lower().count(_s2bytes('netscape')): - version = 'rss091n' + if _s2bytes('netscape') in doctype.lower(): + version = u'rss091n' else: version = None - # only allow in 'safe' inline entity definitions - replacement=_s2bytes('') - if len(doctype_results)==1 and entity_results: - safe_pattern=re.compile(_s2bytes('\s+(\w+)\s+"(&#\w+;|[^&"]*)"')) - safe_entities=filter(lambda e: safe_pattern.match(e),entity_results) - if safe_entities: - replacement=_s2bytes('<!DOCTYPE feed [\n <!ENTITY') + _s2bytes('>\n <!ENTITY ').join(safe_entities) + _s2bytes('>\n]>') - data = doctype_pattern.sub(replacement, head) + data - - return version, data, dict(replacement and [(k.decode('utf-8'), v.decode('utf-8')) for k, v in safe_pattern.findall(replacement)]) - -def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, referrer=None, handlers=[], request_headers={}, response_headers={}): + # Re-insert the safe ENTITY declarations if a DOCTYPE was found. + replacement = _s2bytes('') + if len(doctype_results) == 1 and entity_results: + match_safe_entities = lambda e: RE_SAFE_ENTITY_PATTERN.match(e) + safe_entities = filter(match_safe_entities, entity_results) + if safe_entities: + replacement = _s2bytes('<!DOCTYPE feed [\n<!ENTITY') \ + + _s2bytes('>\n<!ENTITY ').join(safe_entities) \ + + _s2bytes('>\n]>') + data = RE_DOCTYPE_PATTERN.sub(replacement, head) + data + + # Precompute the safe entities for the loose parser. + safe_entities = dict((k.decode('utf-8'), v.decode('utf-8')) + for k, v in RE_SAFE_ENTITY_PATTERN.findall(replacement)) + return version, data, safe_entities + +def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, referrer=None, handlers=None, request_headers=None, response_headers=None): '''Parse a feed from a URL, file, stream, or string. - + request_headers, if given, is a dict from http header name to value to add to the request; this overrides internally generated values. ''' + + if handlers is None: + handlers = [] + if request_headers is None: + request_headers = {} + if response_headers is None: + response_headers = {} + result = FeedParserDict() result['feed'] = FeedParserDict() result['entries'] = [] - if _XML_AVAILABLE: - result['bozo'] = 0 + result['bozo'] = 0 if not isinstance(handlers, list): handlers = [handlers] try: @@ -3624,148 +3898,88 @@ def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, refer elif response_headers: result['headers'] = copy.deepcopy(response_headers) + # lowercase all of the HTTP headers for comparisons per RFC 2616 + if 'headers' in result: + http_headers = dict((k.lower(), v) for k, v in result['headers'].items()) + else: + http_headers = {} + # if feed is gzip-compressed, decompress it - if f and data and 'headers' in result: - if gzip and result['headers'].get('content-encoding') == 'gzip': + if f and data and http_headers: + if gzip and 'gzip' in http_headers.get('content-encoding', ''): try: data = gzip.GzipFile(fileobj=_StringIO(data)).read() - except Exception, e: - # Some feeds claim to be gzipped but they're not, so - # we get garbage. Ideally, we should re-request the - # feed without the 'Accept-encoding: gzip' header, - # but we don't. + except (IOError, struct.error), e: + # IOError can occur if the gzip header is bad. + # struct.error can occur if the data is damaged. result['bozo'] = 1 result['bozo_exception'] = e - data = '' - elif zlib and result['headers'].get('content-encoding') == 'deflate': + if isinstance(e, struct.error): + # A gzip header was found but the data is corrupt. + # Ideally, we should re-request the feed without the + # 'Accept-encoding: gzip' header, but we don't. + data = None + elif zlib and 'deflate' in http_headers.get('content-encoding', ''): try: - data = zlib.decompress(data, -zlib.MAX_WBITS) - except Exception, e: - result['bozo'] = 1 - result['bozo_exception'] = e - data = '' + data = zlib.decompress(data) + except zlib.error, e: + try: + # The data may have no headers and no checksum. + data = zlib.decompress(data, -15) + except zlib.error, e: + result['bozo'] = 1 + result['bozo_exception'] = e # save HTTP headers - if 'headers' in result: - if 'etag' in result['headers'] or 'ETag' in result['headers']: - etag = result['headers'].get('etag', result['headers'].get('ETag')) + if http_headers: + if 'etag' in http_headers: + etag = http_headers.get('etag', u'') + if not isinstance(etag, unicode): + etag = etag.decode('utf-8', 'ignore') if etag: result['etag'] = etag - if 'last-modified' in result['headers'] or 'Last-Modified' in result['headers']: - modified = result['headers'].get('last-modified', result['headers'].get('Last-Modified')) + if 'last-modified' in http_headers: + modified = http_headers.get('last-modified', u'') if modified: - result['modified'] = _parse_date(modified) + result['modified'] = modified + result['modified_parsed'] = _parse_date(modified) if hasattr(f, 'url'): - result['href'] = f.url + if not isinstance(f.url, unicode): + result['href'] = f.url.decode('utf-8', 'ignore') + else: + result['href'] = f.url result['status'] = 200 if hasattr(f, 'status'): result['status'] = f.status if hasattr(f, 'close'): f.close() - # there are four encodings to keep track of: - # - http_encoding is the encoding declared in the Content-Type HTTP header - # - xml_encoding is the encoding declared in the <?xml declaration - # - sniffed_encoding is the encoding sniffed from the first 4 bytes of the XML data - # - result['encoding'] is the actual encoding, as per RFC 3023 and a variety of other conflicting specifications - http_headers = result.get('headers', {}) - result['encoding'], http_encoding, xml_encoding, sniffed_xml_encoding, acceptable_content_type = \ - _getCharacterEncoding(http_headers, data) - if http_headers and (not acceptable_content_type): - if http_headers.has_key('content-type') or http_headers.has_key('Content-type'): - bozo_message = '%s is not an XML media type' % http_headers.get('content-type', http_headers.get('Content-type')) - else: - bozo_message = 'no Content-type specified' - result['bozo'] = 1 - result['bozo_exception'] = NonXMLContentType(bozo_message) - - if data is not None: - result['version'], data, entities = _stripDoctype(data) - - # ensure that baseuri is an absolute uri using an acceptable URI scheme - contentloc = http_headers.get('content-location', http_headers.get('Content-Location', '')) - href = result.get('href', '') - baseuri = _makeSafeAbsoluteURI(href, contentloc) or _makeSafeAbsoluteURI(contentloc) or href - - baselang = http_headers.get('content-language', http_headers.get('Content-Language', None)) + if data is None: + return result - # if server sent 304, we're done - if result.get('status', 0) == 304: - result['version'] = '' + # Stop processing if the server sent HTTP 304 Not Modified. + if getattr(f, 'code', 0) == 304: + result['version'] = u'' result['debug_message'] = 'The feed has not changed since you last checked, ' + \ 'so the server sent no data. This is a feature, not a bug!' return result - # if there was a problem downloading, we're done - if data is None: - return result - - # determine character encoding - use_strict_parser = 0 - known_encoding = 0 - tried_encodings = [] - # try: HTTP encoding, declared XML encoding, encoding sniffed from BOM - for proposed_encoding in (result['encoding'], xml_encoding, sniffed_xml_encoding): - if not proposed_encoding: continue - if proposed_encoding in tried_encodings: continue - tried_encodings.append(proposed_encoding) - try: - data = _toUTF8(data, proposed_encoding) - known_encoding = use_strict_parser = 1 - break - except: - pass - # if no luck and we have auto-detection library, try that - if (not known_encoding) and chardet: - try: - proposed_encoding = chardet.detect(data)['encoding'] - if proposed_encoding and (proposed_encoding not in tried_encodings): - tried_encodings.append(proposed_encoding) - data = _toUTF8(data, proposed_encoding) - known_encoding = use_strict_parser = 1 - except: - pass - # if still no luck and we haven't tried utf-8 yet, try that - if (not known_encoding) and ('utf-8' not in tried_encodings): - try: - proposed_encoding = 'utf-8' - tried_encodings.append(proposed_encoding) - data = _toUTF8(data, proposed_encoding) - known_encoding = use_strict_parser = 1 - except: - pass - # if still no luck and we haven't tried windows-1252 yet, try that - if (not known_encoding) and ('windows-1252' not in tried_encodings): - try: - proposed_encoding = 'windows-1252' - tried_encodings.append(proposed_encoding) - data = _toUTF8(data, proposed_encoding) - known_encoding = use_strict_parser = 1 - except: - pass - # if still no luck and we haven't tried iso-8859-2 yet, try that. - if (not known_encoding) and ('iso-8859-2' not in tried_encodings): - try: - proposed_encoding = 'iso-8859-2' - tried_encodings.append(proposed_encoding) - data = _toUTF8(data, proposed_encoding) - known_encoding = use_strict_parser = 1 - except: - pass - # if still no luck, give up - if not known_encoding: + data, result['encoding'], error = convert_to_utf8(http_headers, data) + use_strict_parser = result['encoding'] and True or False + if error is not None: result['bozo'] = 1 - result['bozo_exception'] = CharacterEncodingUnknown( \ - 'document encoding unknown, I tried ' + \ - '%s, %s, utf-8, windows-1252, and iso-8859-2 but nothing worked' % \ - (result['encoding'], xml_encoding)) - result['encoding'] = '' - elif proposed_encoding != result['encoding']: - result['bozo'] = 1 - result['bozo_exception'] = CharacterEncodingOverride( \ - 'document declared as %s, but parsed as %s' % \ - (result['encoding'], proposed_encoding)) - result['encoding'] = proposed_encoding + result['bozo_exception'] = error + + result['version'], data, entities = replace_doctype(data) + + # Ensure that baseuri is an absolute URI using an acceptable URI scheme. + contentloc = http_headers.get('content-location', u'') + href = result.get('href', u'') + baseuri = _makeSafeAbsoluteURI(href, contentloc) or _makeSafeAbsoluteURI(contentloc) or href + + baselang = http_headers.get('content-language', None) + if not isinstance(baselang, unicode) and baselang is not None: + baselang = baselang.decode('utf-8', 'ignore') if not _XML_AVAILABLE: use_strict_parser = 0 @@ -3774,26 +3988,22 @@ def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, refer feedparser = _StrictFeedParser(baseuri, baselang, 'utf-8') saxparser = xml.sax.make_parser(PREFERRED_XML_PARSERS) saxparser.setFeature(xml.sax.handler.feature_namespaces, 1) + try: + # disable downloading external doctype references, if possible + saxparser.setFeature(xml.sax.handler.feature_external_ges, 0) + except xml.sax.SAXNotSupportedException: + pass saxparser.setContentHandler(feedparser) saxparser.setErrorHandler(feedparser) source = xml.sax.xmlreader.InputSource() source.setByteStream(_StringIO(data)) - if hasattr(saxparser, '_ns_stack'): - # work around bug in built-in SAX parser (doesn't recognize xml: namespace) - # PyXML doesn't have this problem, and it doesn't have _ns_stack either - saxparser._ns_stack.append({'http://www.w3.org/XML/1998/namespace':'xml'}) try: saxparser.parse(source) - except Exception, e: - if _debug: - import traceback - traceback.print_stack() - traceback.print_exc() - sys.stderr.write('xml parsing failed\n') + except xml.sax.SAXException, e: result['bozo'] = 1 result['bozo_exception'] = feedparser.exc or e use_strict_parser = 0 - if not use_strict_parser: + if not use_strict_parser and _SGML_AVAILABLE: feedparser = _LooseFeedParser(baseuri, baselang, 'utf-8', entities) feedparser.feed(data.decode('utf-8', 'replace')) result['feed'] = feedparser.feeddata @@ -3801,85 +4011,3 @@ def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, refer result['version'] = result['version'] or feedparser.version result['namespaces'] = feedparser.namespacesInUse return result - -class Serializer: - def __init__(self, results): - self.results = results - -class TextSerializer(Serializer): - def write(self, stream=sys.stdout): - self._writer(stream, self.results, '') - - def _writer(self, stream, node, prefix): - if not node: return - if hasattr(node, 'keys'): - keys = node.keys() - keys.sort() - for k in keys: - if k in ('description', 'link'): continue - if node.has_key(k + '_detail'): continue - if node.has_key(k + '_parsed'): continue - self._writer(stream, node[k], prefix + k + '.') - elif type(node) == types.ListType: - index = 0 - for n in node: - self._writer(stream, n, prefix[:-1] + '[' + str(index) + '].') - index += 1 - else: - try: - s = str(node).encode('utf-8') - s = s.replace('\\', '\\\\') - s = s.replace('\r', '') - s = s.replace('\n', r'\n') - stream.write(prefix[:-1]) - stream.write('=') - stream.write(s) - stream.write('\n') - except: - pass - -class PprintSerializer(Serializer): - def write(self, stream=sys.stdout): - if self.results.has_key('href'): - stream.write(self.results['href'] + '\n\n') - from pprint import pprint - pprint(self.results, stream) - stream.write('\n') - -if __name__ == '__main__': - try: - from optparse import OptionParser - except: - OptionParser = None - - if OptionParser: - optionParser = OptionParser(version=__version__, usage="%prog [options] url_or_filename_or_-") - optionParser.set_defaults(format="pprint") - optionParser.add_option("-A", "--user-agent", dest="agent", metavar="AGENT", help="User-Agent for HTTP URLs") - optionParser.add_option("-e", "--referer", "--referrer", dest="referrer", metavar="URL", help="Referrer for HTTP URLs") - optionParser.add_option("-t", "--etag", dest="etag", metavar="TAG", help="ETag/If-None-Match for HTTP URLs") - optionParser.add_option("-m", "--last-modified", dest="modified", metavar="DATE", help="Last-modified/If-Modified-Since for HTTP URLs (any supported date format)") - optionParser.add_option("-f", "--format", dest="format", metavar="FORMAT", help="output results in FORMAT (text, pprint)") - optionParser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="write debugging information to stderr") - (options, urls) = optionParser.parse_args() - if options.verbose: - _debug = 1 - if not urls: - optionParser.print_help() - sys.exit(0) - else: - if not sys.argv[1:]: - print __doc__ - sys.exit(0) - class _Options: - etag = modified = agent = referrer = None - format = 'pprint' - options = _Options() - urls = sys.argv[1:] - - zopeCompatibilityHack() - - serializer = globals().get(options.format.capitalize() + 'Serializer', Serializer) - for url in urls: - results = parse(url, etag=options.etag, modified=options.modified, agent=options.agent, referrer=options.referrer) - serializer(results).write(sys.stdout) diff --git a/module/lib/jinja2/__init__.py b/module/lib/jinja2/__init__.py index f944e11b6..a4f7e9c4e 100644 --- a/module/lib/jinja2/__init__.py +++ b/module/lib/jinja2/__init__.py @@ -27,11 +27,7 @@ :license: BSD, see LICENSE for more details. """ __docformat__ = 'restructuredtext en' -try: - __version__ = __import__('pkg_resources') \ - .get_distribution('Jinja2').version -except: - __version__ = 'unknown' +__version__ = '2.7.3' # high level interface from jinja2.environment import Environment, Template diff --git a/module/lib/jinja2/_compat.py b/module/lib/jinja2/_compat.py new file mode 100644 index 000000000..8fa8a49a0 --- /dev/null +++ b/module/lib/jinja2/_compat.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +""" + jinja2._compat + ~~~~~~~~~~~~~~ + + Some py2/py3 compatibility support based on a stripped down + version of six so we don't have to depend on a specific version + of it. + + :copyright: Copyright 2013 by the Jinja team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" +import sys + +PY2 = sys.version_info[0] == 2 +PYPY = hasattr(sys, 'pypy_translation_info') +_identity = lambda x: x + + +if not PY2: + unichr = chr + range_type = range + text_type = str + string_types = (str,) + + iterkeys = lambda d: iter(d.keys()) + itervalues = lambda d: iter(d.values()) + iteritems = lambda d: iter(d.items()) + + import pickle + from io import BytesIO, StringIO + NativeStringIO = StringIO + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + + ifilter = filter + imap = map + izip = zip + intern = sys.intern + + implements_iterator = _identity + implements_to_string = _identity + encode_filename = _identity + get_next = lambda x: x.__next__ + +else: + unichr = unichr + text_type = unicode + range_type = xrange + string_types = (str, unicode) + + iterkeys = lambda d: d.iterkeys() + itervalues = lambda d: d.itervalues() + iteritems = lambda d: d.iteritems() + + import cPickle as pickle + from cStringIO import StringIO as BytesIO, StringIO + NativeStringIO = BytesIO + + exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') + + from itertools import imap, izip, ifilter + intern = intern + + def implements_iterator(cls): + cls.next = cls.__next__ + del cls.__next__ + return cls + + def implements_to_string(cls): + cls.__unicode__ = cls.__str__ + cls.__str__ = lambda x: x.__unicode__().encode('utf-8') + return cls + + get_next = lambda x: x.next + + def encode_filename(filename): + if isinstance(filename, unicode): + return filename.encode('utf-8') + return filename + +try: + next = next +except NameError: + def next(it): + return it.next() + + +def with_metaclass(meta, *bases): + # This requires a bit of explanation: the basic idea is to make a + # dummy metaclass for one level of class instanciation that replaces + # itself with the actual metaclass. Because of internal type checks + # we also need to make sure that we downgrade the custom metaclass + # for one level to something closer to type (that's why __call__ and + # __init__ comes back from type etc.). + # + # This has the advantage over six.with_metaclass in that it does not + # introduce dummy classes into the final MRO. + class metaclass(meta): + __call__ = type.__call__ + __init__ = type.__init__ + def __new__(cls, name, this_bases, d): + if this_bases is None: + return type.__new__(cls, name, (), d) + return meta(name, bases, d) + return metaclass('temporary_class', None, {}) + + +try: + from collections import Mapping as mapping_types +except ImportError: + import UserDict + mapping_types = (UserDict.UserDict, UserDict.DictMixin, dict) + + +# common types. These do exist in the special types module too which however +# does not exist in IronPython out of the box. Also that way we don't have +# to deal with implementation specific stuff here +class _C(object): + def method(self): pass +def _func(): + yield None +function_type = type(_func) +generator_type = type(_func()) +method_type = type(_C().method) +code_type = type(_C.method.__code__) +try: + raise TypeError() +except TypeError: + _tb = sys.exc_info()[2] + traceback_type = type(_tb) + frame_type = type(_tb.tb_frame) + + +try: + from urllib.parse import quote_from_bytes as url_quote +except ImportError: + from urllib import quote as url_quote + + +try: + from thread import allocate_lock +except ImportError: + try: + from threading import Lock as allocate_lock + except ImportError: + from dummy_thread import allocate_lock diff --git a/module/lib/jinja2/_markupsafe/_bundle.py b/module/lib/jinja2/_markupsafe/_bundle.py deleted file mode 100644 index e694faf23..000000000 --- a/module/lib/jinja2/_markupsafe/_bundle.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2._markupsafe._bundle - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This script pulls in markupsafe from a source folder and - bundles it with Jinja2. It does not pull in the speedups - module though. - - :copyright: Copyright 2010 by the Jinja team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" -import sys -import os -import re - - -def rewrite_imports(lines): - for idx, line in enumerate(lines): - new_line = re.sub(r'(import|from)\s+markupsafe\b', - r'\1 jinja2._markupsafe', line) - if new_line != line: - lines[idx] = new_line - - -def main(): - if len(sys.argv) != 2: - print 'error: only argument is path to markupsafe' - sys.exit(1) - basedir = os.path.dirname(__file__) - markupdir = sys.argv[1] - for filename in os.listdir(markupdir): - if filename.endswith('.py'): - f = open(os.path.join(markupdir, filename)) - try: - lines = list(f) - finally: - f.close() - rewrite_imports(lines) - f = open(os.path.join(basedir, filename), 'w') - try: - for line in lines: - f.write(line) - finally: - f.close() - - -if __name__ == '__main__': - main() diff --git a/module/lib/jinja2/_markupsafe/tests.py b/module/lib/jinja2/_markupsafe/tests.py deleted file mode 100644 index c1ce3943a..000000000 --- a/module/lib/jinja2/_markupsafe/tests.py +++ /dev/null @@ -1,80 +0,0 @@ -import gc -import unittest -from jinja2._markupsafe import Markup, escape, escape_silent - - -class MarkupTestCase(unittest.TestCase): - - def test_markup_operations(self): - # adding two strings should escape the unsafe one - unsafe = '<script type="application/x-some-script">alert("foo");</script>' - safe = Markup('<em>username</em>') - assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe) - - # string interpolations are safe to use too - assert Markup('<em>%s</em>') % '<bad user>' == \ - '<em><bad user></em>' - assert Markup('<em>%(username)s</em>') % { - 'username': '<bad user>' - } == '<em><bad user></em>' - - # an escaped object is markup too - assert type(Markup('foo') + 'bar') is Markup - - # and it implements __html__ by returning itself - x = Markup("foo") - assert x.__html__() is x - - # it also knows how to treat __html__ objects - class Foo(object): - def __html__(self): - return '<em>awesome</em>' - def __unicode__(self): - return 'awesome' - assert Markup(Foo()) == '<em>awesome</em>' - assert Markup('<strong>%s</strong>') % Foo() == \ - '<strong><em>awesome</em></strong>' - - # escaping and unescaping - assert escape('"<>&\'') == '"<>&'' - assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar" - assert Markup("<test>").unescape() == "<test>" - - def test_all_set(self): - import jinja2._markupsafe as markup - for item in markup.__all__: - getattr(markup, item) - - def test_escape_silent(self): - assert escape_silent(None) == Markup() - assert escape(None) == Markup(None) - assert escape_silent('<foo>') == Markup(u'<foo>') - - -class MarkupLeakTestCase(unittest.TestCase): - - def test_markup_leaks(self): - counts = set() - for count in xrange(20): - for item in xrange(1000): - escape("foo") - escape("<foo>") - escape(u"foo") - escape(u"<foo>") - counts.add(len(gc.get_objects())) - assert len(counts) == 1, 'ouch, c extension seems to leak objects' - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(MarkupTestCase)) - - # this test only tests the c extension - if not hasattr(escape, 'func_code'): - suite.addTest(unittest.makeSuite(MarkupLeakTestCase)) - - return suite - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/module/lib/jinja2/_stringdefs.py b/module/lib/jinja2/_stringdefs.py index 1161b7f4a..da5830e9f 100644 --- a/module/lib/jinja2/_stringdefs.py +++ b/module/lib/jinja2/_stringdefs.py @@ -13,6 +13,8 @@ :license: BSD, see LICENSE for details. """ +from jinja2._compat import unichr + Cc = u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f' Cf = u'\xad\u0600\u0601\u0602\u0603\u06dd\u070f\u17b4\u17b5\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e\u2060\u2061\u2062\u2063\u206a\u206b\u206c\u206d\u206e\u206f\ufeff\ufff9\ufffa\ufffb' diff --git a/module/lib/jinja2/bccache.py b/module/lib/jinja2/bccache.py index 1e2236c3a..2d28ab8b2 100644 --- a/module/lib/jinja2/bccache.py +++ b/module/lib/jinja2/bccache.py @@ -15,20 +15,46 @@ :license: BSD. """ from os import path, listdir +import os +import stat +import sys +import errno import marshal import tempfile -import cPickle as pickle import fnmatch -from cStringIO import StringIO -try: - from hashlib import sha1 -except ImportError: - from sha import new as sha1 +from hashlib import sha1 from jinja2.utils import open_if_exists +from jinja2._compat import BytesIO, pickle, PY2, text_type -bc_version = 1 -bc_magic = 'j2'.encode('ascii') + pickle.dumps(bc_version, 2) +# marshal works better on 3.x, one hack less required +if not PY2: + marshal_dump = marshal.dump + marshal_load = marshal.load +else: + + def marshal_dump(code, f): + if isinstance(f, file): + marshal.dump(code, f) + else: + f.write(marshal.dumps(code)) + + def marshal_load(f): + if isinstance(f, file): + return marshal.load(f) + return marshal.loads(f.read()) + + +bc_version = 2 + +# magic version used to only change with new jinja versions. With 2.6 +# we change this to also take Python version changes into account. The +# reason for this is that Python tends to segfault if fed earlier bytecode +# versions because someone thought it would be a good idea to reuse opcodes +# or make Python incompatible with earlier versions. +bc_magic = 'j2'.encode('ascii') + \ + pickle.dumps(bc_version, 2) + \ + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1]) class Bucket(object): @@ -62,12 +88,7 @@ class Bucket(object): if self.checksum != checksum: self.reset() return - # now load the code. Because marshal is not able to load - # from arbitrary streams we have to work around that - if isinstance(f, file): - self.code = marshal.load(f) - else: - self.code = marshal.loads(f.read()) + self.code = marshal_load(f) def write_bytecode(self, f): """Dump the bytecode into the file or file like object passed.""" @@ -75,18 +96,15 @@ class Bucket(object): raise TypeError('can\'t write empty bucket') f.write(bc_magic) pickle.dump(self.checksum, f, 2) - if isinstance(f, file): - marshal.dump(self.code, f) - else: - f.write(marshal.dumps(self.code)) + marshal_dump(self.code, f) def bytecode_from_string(self, string): """Load bytecode from a string.""" - self.load_bytecode(StringIO(string)) + self.load_bytecode(BytesIO(string)) def bytecode_to_string(self): """Return the bytecode as string.""" - out = StringIO() + out = BytesIO() self.write_bytecode(out) return out.getvalue() @@ -144,9 +162,10 @@ class BytecodeCache(object): """Returns the unique hash key for this template name.""" hash = sha1(name.encode('utf-8')) if filename is not None: - if isinstance(filename, unicode): + filename = '|' + filename + if isinstance(filename, text_type): filename = filename.encode('utf-8') - hash.update('|' + filename) + hash.update(filename) return hash.hexdigest() def get_source_checksum(self, source): @@ -173,7 +192,9 @@ class FileSystemBytecodeCache(BytecodeCache): two arguments: The directory where the cache items are stored and a pattern string that is used to build the filename. - If no directory is specified the system temporary items folder is used. + If no directory is specified a default cache directory is selected. On + Windows the user's temp directory is used, on UNIX systems a directory + is created for the user in the system temp directory. The pattern can be used to have multiple separate caches operate on the same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` @@ -186,10 +207,38 @@ class FileSystemBytecodeCache(BytecodeCache): def __init__(self, directory=None, pattern='__jinja2_%s.cache'): if directory is None: - directory = tempfile.gettempdir() + directory = self._get_default_cache_dir() self.directory = directory self.pattern = pattern + def _get_default_cache_dir(self): + tmpdir = tempfile.gettempdir() + + # On windows the temporary directory is used specific unless + # explicitly forced otherwise. We can just use that. + if os.name == 'nt': + return tmpdir + if not hasattr(os, 'getuid'): + raise RuntimeError('Cannot determine safe temp directory. You ' + 'need to explicitly provide one.') + + dirname = '_jinja2-cache-%d' % os.getuid() + actual_dir = os.path.join(tmpdir, dirname) + try: + os.mkdir(actual_dir, stat.S_IRWXU) # 0o700 + except OSError as e: + if e.errno != errno.EEXIST: + raise + + actual_dir_stat = os.lstat(actual_dir) + if actual_dir_stat.st_uid != os.getuid() \ + or not stat.S_ISDIR(actual_dir_stat.st_mode) \ + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU: + raise RuntimeError('Temporary directory \'%s\' has an incorrect ' + 'owner, permissions, or type.' % actual_dir) + + return actual_dir + def _get_cache_filename(self, bucket): return path.join(self.directory, self.pattern % bucket.key) @@ -261,15 +310,26 @@ class MemcachedBytecodeCache(BytecodeCache): This bytecode cache does not support clearing of used items in the cache. The clear method is a no-operation function. + + .. versionadded:: 2.7 + Added support for ignoring memcache errors through the + `ignore_memcache_errors` parameter. """ - def __init__(self, client, prefix='jinja2/bytecode/', timeout=None): + def __init__(self, client, prefix='jinja2/bytecode/', timeout=None, + ignore_memcache_errors=True): self.client = client self.prefix = prefix self.timeout = timeout + self.ignore_memcache_errors = ignore_memcache_errors def load_bytecode(self, bucket): - code = self.client.get(self.prefix + bucket.key) + try: + code = self.client.get(self.prefix + bucket.key) + except Exception: + if not self.ignore_memcache_errors: + raise + code = None if code is not None: bucket.bytecode_from_string(code) @@ -277,4 +337,8 @@ class MemcachedBytecodeCache(BytecodeCache): args = (self.prefix + bucket.key, bucket.bytecode_to_string()) if self.timeout is not None: args += (self.timeout,) - self.client.set(*args) + try: + self.client.set(*args) + except Exception: + if not self.ignore_memcache_errors: + raise diff --git a/module/lib/jinja2/compiler.py b/module/lib/jinja2/compiler.py index 57641596a..75a60b8d2 100644 --- a/module/lib/jinja2/compiler.py +++ b/module/lib/jinja2/compiler.py @@ -8,14 +8,16 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD, see LICENSE for more details. """ -from cStringIO import StringIO from itertools import chain from copy import deepcopy +from keyword import iskeyword as is_python_keyword from jinja2 import nodes from jinja2.nodes import EvalContext -from jinja2.visitor import NodeVisitor, NodeTransformer +from jinja2.visitor import NodeVisitor from jinja2.exceptions import TemplateAssertionError -from jinja2.utils import Markup, concat, escape, is_python_keyword, next +from jinja2.utils import Markup, concat, escape +from jinja2._compat import range_type, next, text_type, string_types, \ + iteritems, NativeStringIO, imap operators = { @@ -29,14 +31,6 @@ operators = { 'notin': 'not in' } -try: - exec '(0 if 0 else 0)' -except SyntaxError: - have_condexpr = False -else: - have_condexpr = True - - # what method to iterate over items do we want to use for dict iteration # in generated code? on 2.x let's go with iteritems, on 3.x with items if hasattr(dict, 'iteritems'): @@ -51,7 +45,11 @@ def unoptimize_before_dead_code(): def f(): if 0: dummy(x) return f -unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure) + +# The getattr is necessary for pypy which does not set this attribute if +# no closure is on the function +unoptimize_before_dead_code = bool( + getattr(unoptimize_before_dead_code(), '__closure__', None)) def generate(node, environment, name, filename, stream=None, @@ -69,8 +67,8 @@ def has_safe_repr(value): """Does the node have a safe representation?""" if value is None or value is NotImplemented or value is Ellipsis: return True - if isinstance(value, (bool, int, long, float, complex, basestring, - xrange, Markup)): + if isinstance(value, (bool, int, float, complex, range_type, + Markup) + string_types): return True if isinstance(value, (tuple, list, set, frozenset)): for item in value: @@ -78,7 +76,7 @@ def has_safe_repr(value): return False return True elif isinstance(value, dict): - for key, value in value.iteritems(): + for key, value in iteritems(value): if not has_safe_repr(key): return False if not has_safe_repr(value): @@ -127,12 +125,10 @@ class Identifiers(object): self.undeclared.discard(name) self.declared.add(name) - def is_declared(self, name, local_only=False): + def is_declared(self, name): """Check if a name is declared in this or an outer scope.""" if name in self.declared_locally or name in self.declared_parameter: return True - if local_only: - return False return name in self.declared def copy(self): @@ -193,12 +189,12 @@ class Frame(object): rv.identifiers.__dict__.update(self.identifiers.__dict__) return rv - def inspect(self, nodes, hard_scope=False): + def inspect(self, nodes): """Walk the node and check for identifiers. If the scope is hard (eg: enforce on a python level) overrides from outer scopes are tracked differently. """ - visitor = FrameIdentifierVisitor(self.identifiers, hard_scope) + visitor = FrameIdentifierVisitor(self.identifiers) for node in nodes: visitor.visit(node) @@ -275,9 +271,8 @@ class UndeclaredNameVisitor(NodeVisitor): class FrameIdentifierVisitor(NodeVisitor): """A visitor for `Frame.inspect`.""" - def __init__(self, identifiers, hard_scope): + def __init__(self, identifiers): self.identifiers = identifiers - self.hard_scope = hard_scope def visit_Name(self, node): """All assignments to names go through this function.""" @@ -286,7 +281,7 @@ class FrameIdentifierVisitor(NodeVisitor): elif node.ctx == 'param': self.identifiers.declared_parameter.add(node.name) elif node.ctx == 'load' and not \ - self.identifiers.is_declared(node.name, self.hard_scope): + self.identifiers.is_declared(node.name): self.identifiers.undeclared.add(node.name) def visit_If(self, node): @@ -371,7 +366,7 @@ class CodeGenerator(NodeVisitor): def __init__(self, environment, name, filename, stream=None, defer_init=False): if stream is None: - stream = StringIO() + stream = NativeStringIO() self.environment = environment self.name = name self.filename = filename @@ -545,7 +540,7 @@ class CodeGenerator(NodeVisitor): self.write(', ') self.visit(kwarg, frame) if extra_kwargs is not None: - for key, value in extra_kwargs.iteritems(): + for key, value in iteritems(extra_kwargs): self.write(', %s=%s' % (key, value)) if node.dyn_args: self.write(', *') @@ -561,7 +556,7 @@ class CodeGenerator(NodeVisitor): self.visit(kwarg.value, frame) self.write(', ') if extra_kwargs is not None: - for key, value in extra_kwargs.iteritems(): + for key, value in iteritems(extra_kwargs): self.write('%r: %s, ' % (key, value)) if node.dyn_kwargs is not None: self.write('}, **') @@ -628,7 +623,7 @@ class CodeGenerator(NodeVisitor): def pop_scope(self, aliases, frame): """Restore all aliases and delete unused variables.""" - for name, alias in aliases.iteritems(): + for name, alias in iteritems(aliases): self.writeline('l_%s = %s' % (name, alias)) to_delete = set() for name in frame.identifiers.declared_locally: @@ -658,7 +653,7 @@ class CodeGenerator(NodeVisitor): children = node.iter_child_nodes() children = list(children) func_frame = frame.inner() - func_frame.inspect(children, hard_scope=True) + func_frame.inspect(children) # variables that are undeclared (accessed before declaration) and # declared locally *and* part of an outside scope raise a template @@ -666,16 +661,16 @@ class CodeGenerator(NodeVisitor): # it without aliasing all the variables. # this could be fixed in Python 3 where we have the nonlocal # keyword or if we switch to bytecode generation - overriden_closure_vars = ( + overridden_closure_vars = ( func_frame.identifiers.undeclared & func_frame.identifiers.declared & (func_frame.identifiers.declared_locally | func_frame.identifiers.declared_parameter) ) - if overriden_closure_vars: + if overridden_closure_vars: self.fail('It\'s not possible to set and access variables ' 'derived from an outer scope! (affects: %s)' % - ', '.join(sorted(overriden_closure_vars)), node.lineno) + ', '.join(sorted(overridden_closure_vars)), node.lineno) # remove variables from a closure from the frame's undeclared # identifiers. @@ -830,7 +825,7 @@ class CodeGenerator(NodeVisitor): self.outdent(2 + (not self.has_known_extends)) # at this point we now have the blocks collected and can visit them too. - for name, block in self.blocks.iteritems(): + for name, block in iteritems(self.blocks): block_frame = Frame(eval_ctx) block_frame.inspect(block.body) block_frame.block = name @@ -897,12 +892,13 @@ class CodeGenerator(NodeVisitor): self.indent() self.writeline('raise TemplateRuntimeError(%r)' % 'extended multiple times') - self.outdent() # if we have a known extends already we don't need that code here # as we know that the template execution will end here. if self.has_known_extends: raise CompilerExit() + else: + self.outdent() self.writeline('parent_template = environment.get_template(', node) self.visit(node.template, frame) @@ -933,7 +929,7 @@ class CodeGenerator(NodeVisitor): func_name = 'get_or_select_template' if isinstance(node.template, nodes.Const): - if isinstance(node.template.value, basestring): + if isinstance(node.template.value, string_types): func_name = 'get_template' elif isinstance(node.template.value, (tuple, list)): func_name = 'select_template' @@ -1035,7 +1031,7 @@ class CodeGenerator(NodeVisitor): discarded_names[0]) else: self.writeline('context.exported_vars.difference_' - 'update((%s))' % ', '.join(map(repr, discarded_names))) + 'update((%s))' % ', '.join(imap(repr, discarded_names))) def visit_For(self, node, frame): # when calculating the nodes for the inner frame we have to exclude @@ -1063,7 +1059,7 @@ class CodeGenerator(NodeVisitor): # otherwise we set up a buffer and add a function def else: - self.writeline('def loop(reciter, loop_render_func):', node) + self.writeline('def loop(reciter, loop_render_func, depth=0):', node) self.indent() self.buffer(loop_frame) aliases = {} @@ -1071,6 +1067,7 @@ class CodeGenerator(NodeVisitor): # make sure the loop variable is a special one and raise a template # assertion error if a loop tries to write to loop if extended_loop: + self.writeline('l_loop = missing') loop_frame.identifiers.add_special('loop') for name in node.find_all(nodes.Name): if name.ctx == 'store' and name.name == 'loop': @@ -1089,7 +1086,7 @@ class CodeGenerator(NodeVisitor): node.iter_child_nodes(only=('else_', 'test')), ('loop',)): self.writeline("l_loop = environment.undefined(%r, name='loop')" % ("'loop' is undefined. the filter section of a loop as well " - "as the else block doesn't have access to the special 'loop'" + "as the else block don't have access to the special 'loop'" " variable of the current loop. Because there is no parent " "loop it's undefined. Happened in loop on %s" % self.position(node))) @@ -1121,7 +1118,7 @@ class CodeGenerator(NodeVisitor): self.visit(node.iter, loop_frame) if node.recursive: - self.write(', recurse=loop_render_func):') + self.write(', loop_render_func, depth):') else: self.write(extended_loop and '):' or ':') @@ -1219,9 +1216,9 @@ class CodeGenerator(NodeVisitor): return if self.environment.finalize: - finalize = lambda x: unicode(self.environment.finalize(x)) + finalize = lambda x: text_type(self.environment.finalize(x)) else: - finalize = unicode + finalize = text_type # if we are inside a frame that requires output checking, we do so outdent_later = False @@ -1249,7 +1246,7 @@ class CodeGenerator(NodeVisitor): else: const = escape(const) const = finalize(const) - except: + except Exception: # if something goes wrong here we evaluate the node # at runtime for easier debugging body.append(child) @@ -1370,7 +1367,7 @@ class CodeGenerator(NodeVisitor): public_names[0]) else: self.writeline('context.exported_vars.update((%s))' % - ', '.join(map(repr, public_names))) + ', '.join(imap(repr, public_names))) # -- Expression Visitors @@ -1421,19 +1418,31 @@ class CodeGenerator(NodeVisitor): self.visit(item.value, frame) self.write('}') - def binop(operator): + def binop(operator, interceptable=True): def visitor(self, node, frame): - self.write('(') - self.visit(node.left, frame) - self.write(' %s ' % operator) - self.visit(node.right, frame) + if self.environment.sandboxed and \ + operator in self.environment.intercepted_binops: + self.write('environment.call_binop(context, %r, ' % operator) + self.visit(node.left, frame) + self.write(', ') + self.visit(node.right, frame) + else: + self.write('(') + self.visit(node.left, frame) + self.write(' %s ' % operator) + self.visit(node.right, frame) self.write(')') return visitor - def uaop(operator): + def uaop(operator, interceptable=True): def visitor(self, node, frame): - self.write('(' + operator) - self.visit(node.node, frame) + if self.environment.sandboxed and \ + operator in self.environment.intercepted_unops: + self.write('environment.call_unop(context, %r, ' % operator) + self.visit(node.node, frame) + else: + self.write('(' + operator) + self.visit(node.node, frame) self.write(')') return visitor @@ -1444,11 +1453,11 @@ class CodeGenerator(NodeVisitor): visit_FloorDiv = binop('//') visit_Pow = binop('**') visit_Mod = binop('%') - visit_And = binop('and') - visit_Or = binop('or') + visit_And = binop('and', interceptable=False) + visit_Or = binop('or', interceptable=False) visit_Pos = uaop('+') visit_Neg = uaop('-') - visit_Not = uaop('not ') + visit_Not = uaop('not ', interceptable=False) del binop, uaop def visit_Concat(self, node, frame): @@ -1546,22 +1555,13 @@ class CodeGenerator(NodeVisitor): 'expression on %s evaluated to false and ' 'no else section was defined.' % self.position(node))) - if not have_condexpr: - self.write('((') - self.visit(node.test, frame) - self.write(') and (') - self.visit(node.expr1, frame) - self.write(',) or (') - write_expr2() - self.write(',))[0]') - else: - self.write('(') - self.visit(node.expr1, frame) - self.write(' if ') - self.visit(node.test, frame) - self.write(' else ') - write_expr2() - self.write(')') + self.write('(') + self.visit(node.expr1, frame) + self.write(' if ') + self.visit(node.test, frame) + self.write(' else ') + write_expr2() + self.write(')') def visit_Call(self, node, frame, forward_caller=False): if self.environment.sandboxed: diff --git a/module/lib/jinja2/debug.py b/module/lib/jinja2/debug.py index eb15456d1..815cc18a4 100644 --- a/module/lib/jinja2/debug.py +++ b/module/lib/jinja2/debug.py @@ -12,13 +12,21 @@ """ import sys import traceback -from jinja2.utils import CodeType, missing, internal_code +from types import TracebackType +from jinja2.utils import missing, internal_code from jinja2.exceptions import TemplateSyntaxError +from jinja2._compat import iteritems, reraise, code_type + +# on pypy we can take advantage of transparent proxies +try: + from __pypy__ import tproxy +except ImportError: + tproxy = None # how does the raise helper look like? try: - exec "raise TypeError, 'foo'" + exec("raise TypeError, 'foo'") except SyntaxError: raise_helper = 'raise __jinja_exception__[1]' except TypeError: @@ -30,17 +38,22 @@ class TracebackFrameProxy(object): def __init__(self, tb): self.tb = tb + self._tb_next = None - def _set_tb_next(self, next): - if tb_set_next is not None: - tb_set_next(self.tb, next and next.tb or None) - self._tb_next = next - - def _get_tb_next(self): + @property + def tb_next(self): return self._tb_next - tb_next = property(_get_tb_next, _set_tb_next) - del _get_tb_next, _set_tb_next + def set_next(self, next): + if tb_set_next is not None: + try: + tb_set_next(self.tb, next and next.tb or None) + except Exception: + # this function can fail due to all the hackery it does + # on various python implementations. We just catch errors + # down and ignore them if necessary. + pass + self._tb_next = next @property def is_jinja_frame(self): @@ -50,8 +63,22 @@ class TracebackFrameProxy(object): return getattr(self.tb, name) +def make_frame_proxy(frame): + proxy = TracebackFrameProxy(frame) + if tproxy is None: + return proxy + def operation_handler(operation, *args, **kwargs): + if operation in ('__getattribute__', '__getattr__'): + return getattr(proxy, args[0]) + elif operation == '__setattr__': + proxy.__setattr__(*args, **kwargs) + else: + return getattr(proxy, operation)(*args, **kwargs) + return tproxy(TracebackType, operation_handler) + + class ProcessedTraceback(object): - """Holds a Jinja preprocessed traceback for priting or reraising.""" + """Holds a Jinja preprocessed traceback for printing or reraising.""" def __init__(self, exc_type, exc_value, frames): assert frames, 'no frames for this traceback?' @@ -59,14 +86,13 @@ class ProcessedTraceback(object): self.exc_value = exc_value self.frames = frames - def chain_frames(self): - """Chains the frames. Requires ctypes or the debugsupport extension.""" + # newly concatenate the frames (which are proxies) prev_tb = None for tb in self.frames: if prev_tb is not None: - prev_tb.tb_next = tb + prev_tb.set_next(tb) prev_tb = tb - prev_tb.tb_next = None + prev_tb.set_next(None) def render_as_text(self, limit=None): """Return a string with the traceback.""" @@ -95,7 +121,12 @@ class ProcessedTraceback(object): @property def standard_exc_info(self): """Standard python exc_info for re-raising""" - return self.exc_type, self.exc_value, self.frames[0].tb + tb = self.frames[0] + # the frame will be an actual traceback (or transparent proxy) if + # we are on pypy or a python implementation with support for tproxy + if type(tb) is not TracebackType: + tb = tb.tb + return self.exc_type, self.exc_value, tb def make_traceback(exc_info, source_hint=None): @@ -128,7 +159,7 @@ def translate_exception(exc_info, initial_skip=0): frames = [] # skip some internal frames if wanted - for x in xrange(initial_skip): + for x in range(initial_skip): if tb is not None: tb = tb.tb_next initial_tb = tb @@ -152,19 +183,16 @@ def translate_exception(exc_info, initial_skip=0): tb = fake_exc_info(exc_info[:2] + (tb,), template.filename, lineno)[2] - frames.append(TracebackFrameProxy(tb)) + frames.append(make_frame_proxy(tb)) tb = next # if we don't have any exceptions in the frames left, we have to # reraise it unchanged. # XXX: can we backup here? when could this happen? if not frames: - raise exc_info[0], exc_info[1], exc_info[2] + reraise(exc_info[0], exc_info[1], exc_info[2]) - traceback = ProcessedTraceback(exc_info[0], exc_info[1], frames) - if tb_set_next is not None: - traceback.chain_frames() - return traceback + return ProcessedTraceback(exc_info[0], exc_info[1], frames) def fake_exc_info(exc_info, filename, lineno): @@ -179,7 +207,7 @@ def fake_exc_info(exc_info, filename, lineno): locals = ctx.get_all() else: locals = {} - for name, value in real_locals.iteritems(): + for name, value in iteritems(real_locals): if name.startswith('l_') and value is not missing: locals[name[2:]] = value @@ -217,17 +245,17 @@ def fake_exc_info(exc_info, filename, lineno): location = 'block "%s"' % function[6:] else: location = 'template' - code = CodeType(0, code.co_nlocals, code.co_stacksize, - code.co_flags, code.co_code, code.co_consts, - code.co_names, code.co_varnames, filename, - location, code.co_firstlineno, - code.co_lnotab, (), ()) + code = code_type(0, code.co_nlocals, code.co_stacksize, + code.co_flags, code.co_code, code.co_consts, + code.co_names, code.co_varnames, filename, + location, code.co_firstlineno, + code.co_lnotab, (), ()) except: pass # execute the code and catch the new traceback try: - exec code in globals, locals + exec(code, globals, locals) except: exc_info = sys.exc_info() new_tb = exc_info[2].tb_next @@ -239,7 +267,8 @@ def fake_exc_info(exc_info, filename, lineno): def _init_ugly_crap(): """This function implements a few ugly things so that we can patch the traceback objects. The function returned allows resetting `tb_next` on - any python traceback object. + any python traceback object. Do not attempt to use this on non cpython + interpreters """ import ctypes from types import TracebackType @@ -297,12 +326,12 @@ def _init_ugly_crap(): return tb_set_next -# try to get a tb_set_next implementation -try: - from jinja2._debugsupport import tb_set_next -except ImportError: +# try to get a tb_set_next implementation if we don't have transparent +# proxies. +tb_set_next = None +if tproxy is None: try: tb_set_next = _init_ugly_crap() except: - tb_set_next = None -del _init_ugly_crap + pass + del _init_ugly_crap diff --git a/module/lib/jinja2/defaults.py b/module/lib/jinja2/defaults.py index d2d45443a..a27cb80cb 100644 --- a/module/lib/jinja2/defaults.py +++ b/module/lib/jinja2/defaults.py @@ -8,6 +8,7 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD, see LICENSE for more details. """ +from jinja2._compat import range_type from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner @@ -21,14 +22,16 @@ COMMENT_END_STRING = '#}' LINE_STATEMENT_PREFIX = None LINE_COMMENT_PREFIX = None TRIM_BLOCKS = False +LSTRIP_BLOCKS = False NEWLINE_SEQUENCE = '\n' +KEEP_TRAILING_NEWLINE = False # default filters, tests and namespace from jinja2.filters import FILTERS as DEFAULT_FILTERS from jinja2.tests import TESTS as DEFAULT_TESTS DEFAULT_NAMESPACE = { - 'range': xrange, + 'range': range_type, 'dict': lambda **kw: kw, 'lipsum': generate_lorem_ipsum, 'cycler': Cycler, diff --git a/module/lib/jinja2/environment.py b/module/lib/jinja2/environment.py index ac74a5c68..45fabada2 100644 --- a/module/lib/jinja2/environment.py +++ b/module/lib/jinja2/environment.py @@ -11,16 +11,26 @@ import os import sys from jinja2 import nodes -from jinja2.defaults import * +from jinja2.defaults import BLOCK_START_STRING, \ + BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \ + COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \ + LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \ + DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE, \ + KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS from jinja2.lexer import get_lexer, TokenStream from jinja2.parser import Parser +from jinja2.nodes import EvalContext from jinja2.optimizer import optimize from jinja2.compiler import generate from jinja2.runtime import Undefined, new_context from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \ - TemplatesNotFound + TemplatesNotFound, TemplateRuntimeError from jinja2.utils import import_string, LRUCache, Markup, missing, \ - concat, consume, internalcode, _encode_filename + concat, consume, internalcode +from jinja2._compat import imap, ifilter, string_types, iteritems, \ + text_type, reraise, implements_iterator, implements_to_string, \ + get_next, encode_filename, PY2, PYPY +from functools import reduce # for direct template usage we have up to ten living environments @@ -67,11 +77,11 @@ def copy_cache(cache): def load_extensions(environment, extensions): """Load the extensions from the list and bind it to the environment. - Returns a dict of instanciated environments. + Returns a dict of instantiated environments. """ result = {} for extension in extensions: - if isinstance(extension, basestring): + if isinstance(extension, string_types): extension = import_string(extension) result[extension.identifier] = extension(environment) return result @@ -134,12 +144,23 @@ class Environment(object): If this is set to ``True`` the first newline after a block is removed (block, not variable tag!). Defaults to `False`. + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + `newline_sequence` The sequence that starts a newline. Must be one of ``'\r'``, ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a useful default for Linux and OS X systems as well as web applications. + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + `extensions` List of Jinja extensions to use. This can either be import paths as strings or extension classes. For more information have a @@ -196,7 +217,8 @@ class Environment(object): #: if this environment is sandboxed. Modifying this variable won't make #: the environment sandboxed though. For a real sandboxed environment - #: have a look at jinja2.sandbox + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. sandboxed = False #: True if the environment is just an overlay @@ -223,7 +245,9 @@ class Environment(object): line_statement_prefix=LINE_STATEMENT_PREFIX, line_comment_prefix=LINE_COMMENT_PREFIX, trim_blocks=TRIM_BLOCKS, + lstrip_blocks=LSTRIP_BLOCKS, newline_sequence=NEWLINE_SEQUENCE, + keep_trailing_newline=KEEP_TRAILING_NEWLINE, extensions=(), optimized=True, undefined=Undefined, @@ -238,7 +262,7 @@ class Environment(object): # passed by keyword rather than position. However it's important to # not change the order of arguments because it's used at least # internally in those cases: - # - spontaneus environments (i18n extension and Template) + # - spontaneous environments (i18n extension and Template) # - unittests # If parameter changes are required only add parameters at the end # and don't change the arguments (or the defaults!) of the arguments @@ -254,7 +278,9 @@ class Environment(object): self.line_statement_prefix = line_statement_prefix self.line_comment_prefix = line_comment_prefix self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline # runtime information self.undefined = undefined @@ -269,7 +295,6 @@ class Environment(object): # set the loader provided self.loader = loader - self.bytecode_cache = None self.cache = create_cache(cache_size) self.bytecode_cache = bytecode_cache self.auto_reload = auto_reload @@ -291,7 +316,7 @@ class Environment(object): yet. This is used by :ref:`extensions <writing-extensions>` to register callbacks and configuration values without breaking inheritance. """ - for key, value in attributes.iteritems(): + for key, value in iteritems(attributes): if not hasattr(self, key): setattr(self, key, value) @@ -299,7 +324,8 @@ class Environment(object): variable_start_string=missing, variable_end_string=missing, comment_start_string=missing, comment_end_string=missing, line_statement_prefix=missing, line_comment_prefix=missing, - trim_blocks=missing, extensions=missing, optimized=missing, + trim_blocks=missing, lstrip_blocks=missing, + extensions=missing, optimized=missing, undefined=missing, finalize=missing, autoescape=missing, loader=missing, cache_size=missing, auto_reload=missing, bytecode_cache=missing): @@ -322,7 +348,7 @@ class Environment(object): rv.overlayed = True rv.linked_to = self - for key, value in args.iteritems(): + for key, value in iteritems(args): if value is not missing: setattr(rv, key, value) @@ -332,7 +358,7 @@ class Environment(object): rv.cache = copy_cache(self.cache) rv.extensions = {} - for key, value in self.extensions.iteritems(): + for key, value in iteritems(self.extensions): rv.extensions[key] = value.bind(rv) if extensions is not missing: rv.extensions.update(load_extensions(rv, extensions)) @@ -351,10 +377,10 @@ class Environment(object): try: return obj[argument] except (TypeError, LookupError): - if isinstance(argument, basestring): + if isinstance(argument, string_types): try: attr = str(argument) - except: + except Exception: pass else: try: @@ -376,6 +402,42 @@ class Environment(object): except (TypeError, LookupError, AttributeError): return self.undefined(obj=obj, name=attribute) + def call_filter(self, name, value, args=None, kwargs=None, + context=None, eval_ctx=None): + """Invokes a filter on a value the same way the compiler does it. + + .. versionadded:: 2.7 + """ + func = self.filters.get(name) + if func is None: + raise TemplateRuntimeError('no filter named %r' % name) + args = [value] + list(args or ()) + if getattr(func, 'contextfilter', False): + if context is None: + raise TemplateRuntimeError('Attempted to invoke context ' + 'filter without context') + args.insert(0, context) + elif getattr(func, 'evalcontextfilter', False): + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + args.insert(0, eval_ctx) + elif getattr(func, 'environmentfilter', False): + args.insert(0, self) + return func(*args, **(kwargs or {})) + + def call_test(self, name, value, args=None, kwargs=None): + """Invokes a test on a value the same way the compiler does it. + + .. versionadded:: 2.7 + """ + func = self.tests.get(name) + if func is None: + raise TemplateRuntimeError('no test named %r' % name) + return func(value, *(args or ()), **(kwargs or {})) + @internalcode def parse(self, source, name=None, filename=None): """Parse the sourcecode and return the abstract syntax tree. This @@ -394,7 +456,7 @@ class Environment(object): def _parse(self, source, name, filename): """Internal parsing function used by `parse` and `compile`.""" - return Parser(self, source, name, _encode_filename(filename)).parse() + return Parser(self, source, name, encode_filename(filename)).parse() def lex(self, source, name=None, filename=None): """Lex the given sourcecode and return a generator that yields @@ -406,7 +468,7 @@ class Environment(object): of the extensions to be applied you have to filter source through the :meth:`preprocess` method. """ - source = unicode(source) + source = text_type(source) try: return self.lexer.tokeniter(source, name, filename) except TemplateSyntaxError: @@ -419,7 +481,7 @@ class Environment(object): because there you usually only want the actual source tokenized. """ return reduce(lambda s, e: e.preprocess(s, name, filename), - self.iter_extensions(), unicode(source)) + self.iter_extensions(), text_type(source)) def _tokenize(self, source, name, filename=None, state=None): """Called by the parser to do the preprocessing and filtering @@ -434,7 +496,7 @@ class Environment(object): return stream def _generate(self, source, name, filename, defer_init=False): - """Internal hook that can be overriden to hook a different generate + """Internal hook that can be overridden to hook a different generate method in. .. versionadded:: 2.5 @@ -442,7 +504,7 @@ class Environment(object): return generate(source, self, name, filename, defer_init=defer_init) def _compile(self, source, filename): - """Internal hook that can be overriden to hook a different compile + """Internal hook that can be overridden to hook a different compile method in. .. versionadded:: 2.5 @@ -473,7 +535,7 @@ class Environment(object): """ source_hint = None try: - if isinstance(source, basestring): + if isinstance(source, string_types): source_hint = source source = self._parse(source, name, filename) if self.optimized: @@ -485,7 +547,7 @@ class Environment(object): if filename is None: filename = '<template>' else: - filename = _encode_filename(filename) + filename = encode_filename(filename) return self._compile(source, filename) except TemplateSyntaxError: exc_info = sys.exc_info() @@ -539,7 +601,7 @@ class Environment(object): def compile_templates(self, target, extensions=None, filter_func=None, zip='deflated', log_function=None, ignore_errors=True, py_compile=False): - """Compiles all the templates the loader can find, compiles them + """Finds all the templates the loader can find, compiles them and stores them in `target`. If `zip` is `None`, instead of in a zipfile, the templates will be will be stored in a directory. By default a deflate zip algorithm is used, to switch to @@ -555,7 +617,9 @@ class Environment(object): to `False` and you will get an exception on syntax errors. If `py_compile` is set to `True` .pyc files will be written to the - target instead of standard .py files. + target instead of standard .py files. This flag does not do anything + on pypy and Python 3 where pyc files are not picked up by itself and + don't give much benefit. .. versionadded:: 2.4 """ @@ -565,14 +629,23 @@ class Environment(object): log_function = lambda x: None if py_compile: - import imp, struct, marshal - py_header = imp.get_magic() + \ - u'\xff\xff\xff\xff'.encode('iso-8859-15') + if not PY2 or PYPY: + from warnings import warn + warn(Warning('py_compile has no effect on pypy or Python 3')) + py_compile = False + else: + import imp, marshal + py_header = imp.get_magic() + \ + u'\xff\xff\xff\xff'.encode('iso-8859-15') + + # Python 3.3 added a source filesize to the header + if sys.version_info >= (3, 3): + py_header += u'\x00\x00\x00\x00'.encode('iso-8859-15') def write_file(filename, data, mode): if zip: info = ZipInfo(filename) - info.external_attr = 0755 << 16L + info.external_attr = 0o755 << 16 zip_file.writestr(info, data) else: f = open(os.path.join(target, filename), mode) @@ -596,7 +669,7 @@ class Environment(object): source, filename, _ = self.loader.get_source(self, name) try: code = self.compile(source, name, filename, True, True) - except TemplateSyntaxError, e: + except TemplateSyntaxError as e: if not ignore_errors: raise log_function('Could not compile "%s": %s' % (name, e)) @@ -605,7 +678,7 @@ class Environment(object): filename = ModuleLoader.get_module_filename(name) if py_compile: - c = self._compile(code, _encode_filename(filename)) + c = self._compile(code, encode_filename(filename)) write_file(filename + 'c', py_header + marshal.dumps(c), 'wb') log_function('Byte-compiled "%s" as %s' % @@ -632,6 +705,8 @@ class Environment(object): in the result list. If the loader does not support that, a :exc:`TypeError` is raised. + + .. versionadded:: 2.4 """ x = self.loader.list_templates() if extensions is not None: @@ -641,7 +716,7 @@ class Environment(object): filter_func = lambda x: '.' in x and \ x.rsplit('.', 1)[1] in extensions if filter_func is not None: - x = filter(filter_func, x) + x = ifilter(filter_func, x) return x def handle_exception(self, exc_info=None, rendered=False, source_hint=None): @@ -664,7 +739,7 @@ class Environment(object): if self.exception_handler is not None: self.exception_handler(traceback) exc_type, exc_value, tb = traceback.standard_exc_info - raise exc_type, exc_value, tb + reraise(exc_type, exc_value, tb) def join_path(self, template, parent): """Join a template with the parent. By default all the lookups are @@ -751,7 +826,7 @@ class Environment(object): .. versionadded:: 2.3 """ - if isinstance(template_name_or_list, basestring): + if isinstance(template_name_or_list, string_types): return self.get_template(template_name_or_list, parent, globals) elif isinstance(template_name_or_list, Template): return template_name_or_list @@ -813,7 +888,9 @@ class Template(object): line_statement_prefix=LINE_STATEMENT_PREFIX, line_comment_prefix=LINE_COMMENT_PREFIX, trim_blocks=TRIM_BLOCKS, + lstrip_blocks=LSTRIP_BLOCKS, newline_sequence=NEWLINE_SEQUENCE, + keep_trailing_newline=KEEP_TRAILING_NEWLINE, extensions=(), optimized=True, undefined=Undefined, @@ -823,8 +900,9 @@ class Template(object): block_start_string, block_end_string, variable_start_string, variable_end_string, comment_start_string, comment_end_string, line_statement_prefix, line_comment_prefix, trim_blocks, - newline_sequence, frozenset(extensions), optimized, undefined, - finalize, autoescape, None, 0, False, None) + lstrip_blocks, newline_sequence, keep_trailing_newline, + frozenset(extensions), optimized, undefined, finalize, autoescape, + None, 0, False, None) return env.from_string(source, template_class=cls) @classmethod @@ -836,7 +914,7 @@ class Template(object): 'environment': environment, '__file__': code.co_filename } - exec code in namespace + exec(code, namespace) rv = cls._from_namespace(environment, namespace, globals) rv._uptodate = uptodate return rv @@ -886,7 +964,7 @@ class Template(object): vars = dict(*args, **kwargs) try: return concat(self.root_render_func(self.new_context(vars))) - except: + except Exception: exc_info = sys.exc_info() return self.environment.handle_exception(exc_info, True) @@ -908,7 +986,7 @@ class Template(object): try: for event in self.root_render_func(self.new_context(vars)): yield event - except: + except Exception: exc_info = sys.exc_info() else: return @@ -970,7 +1048,7 @@ class Template(object): @property def debug_info(self): """The debug info mapping.""" - return [tuple(map(int, x.split('='))) for x in + return [tuple(imap(int, x.split('='))) for x in self._debug_info.split('&')] def __repr__(self): @@ -981,6 +1059,7 @@ class Template(object): return '<%s %s>' % (self.__class__.__name__, name) +@implements_to_string class TemplateModule(object): """Represents an imported template. All the exported names of the template are available as attributes on this object. Additionally @@ -996,13 +1075,6 @@ class TemplateModule(object): return Markup(concat(self._body_stream)) def __str__(self): - return unicode(self).encode('utf-8') - - # unicode goes after __str__ because we configured 2to3 to rename - # __unicode__ to __str__. because the 2to3 tree is not designed to - # remove nodes from it, we leave the above __str__ around and let - # it override at runtime. - def __unicode__(self): return concat(self._body_stream) def __repr__(self): @@ -1032,6 +1104,7 @@ class TemplateExpression(object): return rv +@implements_iterator class TemplateStream(object): """A template stream works pretty much like an ordinary python generator but it can buffer multiple items to reduce the number of total iterations. @@ -1050,15 +1123,15 @@ class TemplateStream(object): def dump(self, fp, encoding=None, errors='strict'): """Dump the complete stream into a file or file-like object. Per default unicode strings are written, if you want to encode - before writing specifiy an `encoding`. + before writing specify an `encoding`. Example usage:: Template('Hello {{ name }}!').stream(name='foo').dump('hello.html') """ close = False - if isinstance(fp, basestring): - fp = file(fp, 'w') + if isinstance(fp, string_types): + fp = open(fp, encoding is None and 'w' or 'wb') close = True try: if encoding is not None: @@ -1076,7 +1149,7 @@ class TemplateStream(object): def disable_buffering(self): """Disable the output buffering.""" - self._next = self._gen.next + self._next = get_next(self._gen) self.buffered = False def enable_buffering(self, size=5): @@ -1104,12 +1177,12 @@ class TemplateStream(object): c_size = 0 self.buffered = True - self._next = generator(self._gen.next).next + self._next = get_next(generator(get_next(self._gen))) def __iter__(self): return self - def next(self): + def __next__(self): return self._next() diff --git a/module/lib/jinja2/exceptions.py b/module/lib/jinja2/exceptions.py index 771f6a8d7..c9df6dc7c 100644 --- a/module/lib/jinja2/exceptions.py +++ b/module/lib/jinja2/exceptions.py @@ -8,24 +8,40 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD, see LICENSE for more details. """ +from jinja2._compat import imap, text_type, PY2, implements_to_string class TemplateError(Exception): """Baseclass for all template errors.""" - def __init__(self, message=None): - if message is not None: - message = unicode(message).encode('utf-8') - Exception.__init__(self, message) - - @property - def message(self): - if self.args: - message = self.args[0] + if PY2: + def __init__(self, message=None): if message is not None: - return message.decode('utf-8', 'replace') - - + message = text_type(message).encode('utf-8') + Exception.__init__(self, message) + + @property + def message(self): + if self.args: + message = self.args[0] + if message is not None: + return message.decode('utf-8', 'replace') + + def __unicode__(self): + return self.message or u'' + else: + def __init__(self, message=None): + Exception.__init__(self, message) + + @property + def message(self): + if self.args: + message = self.args[0] + if message is not None: + return message + + +@implements_to_string class TemplateNotFound(IOError, LookupError, TemplateError): """Raised if a template does not exist.""" @@ -42,13 +58,6 @@ class TemplateNotFound(IOError, LookupError, TemplateError): self.templates = [name] def __str__(self): - return self.message.encode('utf-8') - - # unicode goes after __str__ because we configured 2to3 to rename - # __unicode__ to __str__. because the 2to3 tree is not designed to - # remove nodes from it, we leave the above __str__ around and let - # it override at runtime. - def __unicode__(self): return self.message @@ -62,12 +71,13 @@ class TemplatesNotFound(TemplateNotFound): def __init__(self, names=(), message=None): if message is None: - message = u'non of the templates given were found: ' + \ - u', '.join(map(unicode, names)) + message = u'none of the templates given were found: ' + \ + u', '.join(imap(text_type, names)) TemplateNotFound.__init__(self, names and names[-1] or None, message) self.templates = list(names) +@implements_to_string class TemplateSyntaxError(TemplateError): """Raised to tell the user that there is a problem with the template.""" @@ -83,13 +93,6 @@ class TemplateSyntaxError(TemplateError): self.translated = False def __str__(self): - return unicode(self).encode('utf-8') - - # unicode goes after __str__ because we configured 2to3 to rename - # __unicode__ to __str__. because the 2to3 tree is not designed to - # remove nodes from it, we leave the above __str__ around and let - # it override at runtime. - def __unicode__(self): # for translated errors we only return the message if self.translated: return self.message diff --git a/module/lib/jinja2/ext.py b/module/lib/jinja2/ext.py index ceb38953a..c2df12d55 100644 --- a/module/lib/jinja2/ext.py +++ b/module/lib/jinja2/ext.py @@ -10,13 +10,17 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD. """ -from collections import deque from jinja2 import nodes -from jinja2.defaults import * +from jinja2.defaults import BLOCK_START_STRING, \ + BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \ + COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \ + LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \ + KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS from jinja2.environment import Environment -from jinja2.runtime import Undefined, concat +from jinja2.runtime import concat from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError -from jinja2.utils import contextfunction, import_string, Markup, next +from jinja2.utils import contextfunction, import_string, Markup +from jinja2._compat import next, with_metaclass, string_types, iteritems # the only real useful gettext functions for a Jinja template. Note @@ -34,7 +38,7 @@ class ExtensionRegistry(type): return rv -class Extension(object): +class Extension(with_metaclass(ExtensionRegistry, object)): """Extensions can be used to add extra functionality to the Jinja template system at the parser level. Custom extensions are bound to an environment but may not store environment specific data on `self`. The reason for @@ -52,7 +56,6 @@ class Extension(object): is a terrible name, ``fragment_cache_prefix`` on the other hand is a good name as includes the name of the extension (fragment cache). """ - __metaclass__ = ExtensionRegistry #: if this extension parses this is the list of tags it's listening to. tags = set() @@ -103,7 +106,9 @@ class Extension(object): def attr(self, name, lineno=None): """Return an attribute node for the current extension. This is useful - to pass constants on extensions to generated template code:: + to pass constants on extensions to generated template code. + + :: self.attr('_my_attribute', lineno=lineno) """ @@ -203,7 +208,7 @@ class InternationalizationExtension(Extension): self.environment.globals.pop(key, None) def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS): - if isinstance(source, basestring): + if isinstance(source, string_types): source = self.environment.parse(source) return extract_from_ast(source, gettext_functions) @@ -216,6 +221,7 @@ class InternationalizationExtension(Extension): # defined in the body of the trans block too, but this is checked at # a later state. plural_expr = None + plural_expr_assignment = None variables = {} while parser.stream.current.type != 'block_end': if variables: @@ -239,7 +245,13 @@ class InternationalizationExtension(Extension): variables[name.value] = var = nodes.Name(name.value, 'load') if plural_expr is None: - plural_expr = var + if isinstance(var, nodes.Call): + plural_expr = nodes.Name('_trans', 'load') + variables[name.value] = plural_expr + plural_expr_assignment = nodes.Assign( + nodes.Name('_trans', 'store'), var) + else: + plural_expr = var num_called_num = name.value == 'num' parser.stream.expect('block_end') @@ -289,7 +301,10 @@ class InternationalizationExtension(Extension): bool(referenced), num_called_num and have_plural) node.set_lineno(lineno) - return node + if plural_expr_assignment is not None: + return [plural_expr_assignment, node] + else: + return node def _parse_block(self, parser, allow_pluralize): """Parse until the next block tag with a given name.""" @@ -352,7 +367,7 @@ class InternationalizationExtension(Extension): # enough to handle the variable expansion and autoescape # handling itself if self.environment.newstyle_gettext: - for key, value in variables.iteritems(): + for key, value in iteritems(variables): # the function adds that later anyways in case num was # called num, so just skip it. if num_called_num and key == 'num': @@ -474,7 +489,7 @@ def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS, strings = [] for arg in node.args: if isinstance(arg, nodes.Const) and \ - isinstance(arg.value, basestring): + isinstance(arg.value, string_types): strings.append(arg.value) else: strings.append(None) @@ -550,6 +565,10 @@ def babel_extract(fileobj, keywords, comment_tags, options): The `newstyle_gettext` flag can be set to `True` to enable newstyle gettext calls. + .. versionchanged:: 2.7 + A `silent` option can now be provided. If set to `False` template + syntax errors are propagated instead of being ignored. + :param fileobj: the file-like object the messages should be extracted from :param keywords: a list of keywords (i.e. function names) that should be recognized as translation functions @@ -569,8 +588,10 @@ def babel_extract(fileobj, keywords, comment_tags, options): extensions.add(InternationalizationExtension) def getbool(options, key, default=False): - options.get(key, str(default)).lower() in ('1', 'on', 'yes', 'true') + return options.get(key, str(default)).lower() in \ + ('1', 'on', 'yes', 'true') + silent = getbool(options, 'silent', True) environment = Environment( options.get('block_start_string', BLOCK_START_STRING), options.get('block_end_string', BLOCK_END_STRING), @@ -581,7 +602,10 @@ def babel_extract(fileobj, keywords, comment_tags, options): options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX, options.get('line_comment_prefix') or LINE_COMMENT_PREFIX, getbool(options, 'trim_blocks', TRIM_BLOCKS), - NEWLINE_SEQUENCE, frozenset(extensions), + getbool(options, 'lstrip_blocks', LSTRIP_BLOCKS), + NEWLINE_SEQUENCE, + getbool(options, 'keep_trailing_newline', KEEP_TRAILING_NEWLINE), + frozenset(extensions), cache_size=0, auto_reload=False ) @@ -593,7 +617,9 @@ def babel_extract(fileobj, keywords, comment_tags, options): try: node = environment.parse(source) tokens = list(environment.lex(environment.preprocess(source))) - except TemplateSyntaxError, e: + except TemplateSyntaxError as e: + if not silent: + raise # skip templates with syntax errors return diff --git a/module/lib/jinja2/filters.py b/module/lib/jinja2/filters.py index d1848e434..fd0db04aa 100644 --- a/module/lib/jinja2/filters.py +++ b/module/lib/jinja2/filters.py @@ -10,12 +10,15 @@ """ import re import math + from random import choice from operator import itemgetter -from itertools import imap, groupby -from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode +from itertools import groupby +from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \ + unicode_urlencode from jinja2.runtime import Undefined -from jinja2.exceptions import FilterArgumentError, SecurityError +from jinja2.exceptions import FilterArgumentError +from jinja2._compat import next, imap, string_types, text_type, iteritems _word_re = re.compile(r'\w+(?u)') @@ -48,11 +51,50 @@ def environmentfilter(f): return f +def make_attrgetter(environment, attribute): + """Returns a callable that looks up the given attribute from a + passed object with the rules of the environment. Dots are allowed + to access attributes of attributes. Integer parts in paths are + looked up as integers. + """ + if not isinstance(attribute, string_types) \ + or ('.' not in attribute and not attribute.isdigit()): + return lambda x: environment.getitem(x, attribute) + attribute = attribute.split('.') + def attrgetter(item): + for part in attribute: + if part.isdigit(): + part = int(part) + item = environment.getitem(item, part) + return item + return attrgetter + + def do_forceescape(value): """Enforce HTML escaping. This will probably double escape variables.""" if hasattr(value, '__html__'): value = value.__html__() - return escape(unicode(value)) + return escape(text_type(value)) + + +def do_urlencode(value): + """Escape strings for use in URLs (uses UTF-8 encoding). It accepts both + dictionaries and regular strings as well as pairwise iterables. + + .. versionadded:: 2.7 + """ + itemiter = None + if isinstance(value, dict): + itemiter = iteritems(value) + elif not isinstance(value, string_types): + try: + itemiter = iter(value) + except TypeError: + pass + if itemiter is None: + return unicode_urlencode(value) + return u'&'.join(unicode_urlencode(k) + '=' + + unicode_urlencode(v) for k, v in itemiter) @evalcontextfilter @@ -74,7 +116,7 @@ def do_replace(eval_ctx, s, old, new, count=None): if count is None: count = -1 if not eval_ctx.autoescape: - return unicode(s).replace(unicode(old), unicode(new), count) + return text_type(s).replace(text_type(old), text_type(new), count) if hasattr(old, '__html__') or hasattr(new, '__html__') and \ not hasattr(s, '__html__'): s = escape(s) @@ -119,7 +161,7 @@ def do_xmlattr(_eval_ctx, d, autospace=True): """ rv = u' '.join( u'%s="%s"' % (escape(key), escape(value)) - for key, value in d.iteritems() + for key, value in iteritems(d) if value is not None and not isinstance(value, Undefined) ) if autospace and rv: @@ -140,7 +182,12 @@ def do_title(s): """Return a titlecased version of the value. I.e. words will start with uppercase letters, all remaining characters are lowercase. """ - return soft_unicode(s).title() + rv = [] + for item in re.compile(r'([-\s]+)(?u)').split(s): + if not item: + continue + rv.append(item[0].upper() + item[1:].lower()) + return ''.join(rv) def do_dictsort(value, case_sensitive=False, by='key'): @@ -153,7 +200,7 @@ def do_dictsort(value, case_sensitive=False, by='key'): {% for item in mydict|dictsort %} sort the dict by key, case insensitive - {% for item in mydict|dicsort(true) %} + {% for item in mydict|dictsort(true) %} sort the dict by key, case sensitive {% for item in mydict|dictsort(false, 'value') %} @@ -169,14 +216,16 @@ def do_dictsort(value, case_sensitive=False, by='key'): '"key" or "value"') def sort_func(item): value = item[pos] - if isinstance(value, basestring) and not case_sensitive: + if isinstance(value, string_types) and not case_sensitive: value = value.lower() return value return sorted(value.items(), key=sort_func) -def do_sort(value, reverse=False, case_sensitive=False): +@environmentfilter +def do_sort(environment, value, reverse=False, case_sensitive=False, + attribute=None): """Sort an iterable. Per default it sorts ascending, if you pass it true as first argument it will reverse the sorting. @@ -189,14 +238,30 @@ def do_sort(value, reverse=False, case_sensitive=False): {% for item in iterable|sort %} ... {% endfor %} + + It is also possible to sort by an attribute (for example to sort + by the date of an object) by specifying the `attribute` parameter: + + .. sourcecode:: jinja + + {% for item in iterable|sort(attribute='date') %} + ... + {% endfor %} + + .. versionchanged:: 2.6 + The `attribute` parameter was added. """ if not case_sensitive: def sort_func(item): - if isinstance(item, basestring): + if isinstance(item, string_types): item = item.lower() return item else: sort_func = None + if attribute is not None: + getter = make_attrgetter(environment, attribute) + def sort_func(item, processor=sort_func or (lambda x: x)): + return processor(getter(item)) return sorted(value, key=sort_func, reverse=reverse) @@ -217,13 +282,13 @@ def do_default(value, default_value=u'', boolean=False): {{ ''|default('the string was empty', true) }} """ - if (boolean and not value) or isinstance(value, Undefined): + if isinstance(value, Undefined) or (boolean and not value): return default_value return value @evalcontextfilter -def do_join(eval_ctx, value, d=u''): +def do_join(eval_ctx, value, d=u'', attribute=None): """Return a string which is the concatenation of the strings in the sequence. The separator between elements is an empty string per default, you can define it with the optional parameter: @@ -235,10 +300,22 @@ def do_join(eval_ctx, value, d=u''): {{ [1, 2, 3]|join }} -> 123 + + It is also possible to join certain attributes of an object: + + .. sourcecode:: jinja + + {{ users|join(', ', attribute='username') }} + + .. versionadded:: 2.6 + The `attribute` parameter was added. """ + if attribute is not None: + value = imap(make_attrgetter(eval_ctx.environment, attribute), value) + # no automatic escaping? joining is a lot eaiser then if not eval_ctx.autoescape: - return unicode(d).join(imap(unicode, value)) + return text_type(d).join(imap(text_type, value)) # if the delimiter doesn't have an html representation we check # if any of the items has. If yes we do a coercion to Markup @@ -249,11 +326,11 @@ def do_join(eval_ctx, value, d=u''): if hasattr(item, '__html__'): do_escape = True else: - value[idx] = unicode(item) + value[idx] = text_type(item) if do_escape: d = escape(d) else: - d = unicode(d) + d = text_type(d) return d.join(value) # no html involved, to normal joining @@ -262,14 +339,14 @@ def do_join(eval_ctx, value, d=u''): def do_center(value, width=80): """Centers the value in a field of a given width.""" - return unicode(value).center(width) + return text_type(value).center(width) @environmentfilter def do_first(environment, seq): """Return the first item of a sequence.""" try: - return iter(seq).next() + return next(iter(seq)) except StopIteration: return environment.undefined('No first item, sequence was empty.') @@ -278,7 +355,7 @@ def do_first(environment, seq): def do_last(environment, seq): """Return the last item of a sequence.""" try: - return iter(reversed(seq)).next() + return next(iter(reversed(seq))) except StopIteration: return environment.undefined('No last item, sequence was empty.') @@ -293,21 +370,33 @@ def do_random(environment, seq): def do_filesizeformat(value, binary=False): - """Format the value like a 'human-readable' file size (i.e. 13 KB, - 4.1 MB, 102 bytes, etc). Per default decimal prefixes are used (mega, - giga, etc.), if the second parameter is set to `True` the binary - prefixes are used (mebi, gibi). + """Format the value like a 'human-readable' file size (i.e. 13 kB, + 4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega, + Giga, etc.), if the second parameter is set to `True` the binary + prefixes are used (Mebi, Gibi). """ bytes = float(value) base = binary and 1024 or 1000 - middle = binary and 'i' or '' - if bytes < base: - return "%d Byte%s" % (bytes, bytes != 1 and 's' or '') - elif bytes < base * base: - return "%.1f K%sB" % (bytes / base, middle) - elif bytes < base * base * base: - return "%.1f M%sB" % (bytes / (base * base), middle) - return "%.1f G%sB" % (bytes / (base * base * base), middle) + prefixes = [ + (binary and 'KiB' or 'kB'), + (binary and 'MiB' or 'MB'), + (binary and 'GiB' or 'GB'), + (binary and 'TiB' or 'TB'), + (binary and 'PiB' or 'PB'), + (binary and 'EiB' or 'EB'), + (binary and 'ZiB' or 'ZB'), + (binary and 'YiB' or 'YB') + ] + if bytes == 1: + return '1 Byte' + elif bytes < base: + return '%d Bytes' % bytes + else: + for i, prefix in enumerate(prefixes): + unit = base ** (i + 2) + if bytes < unit: + return '%.1f %s' % ((base * bytes / unit), prefix) + return '%.1f %s' % ((base * bytes / unit), prefix) def do_pprint(value, verbose=False): @@ -360,16 +449,17 @@ def do_truncate(s, length=255, killwords=False, end='...'): """Return a truncated copy of the string. The length is specified with the first parameter which defaults to ``255``. If the second parameter is ``true`` the filter will cut the text at length. Otherwise - it will try to save the last word. If the text was in fact + it will discard the last word. If the text was in fact truncated it will append an ellipsis sign (``"..."``). If you want a different ellipsis sign than ``"..."`` you can specify it using the third parameter. - .. sourcecode jinja:: + .. sourcecode:: jinja - {{ mytext|truncate(300, false, '»') }} - truncate mytext to 300 chars, don't split up words, use a - right pointing double arrow as ellipsis sign. + {{ "foo bar"|truncate(5) }} + -> "foo ..." + {{ "foo bar"|truncate(5, True) }} + -> "foo b..." """ if len(s) <= length: return s @@ -386,16 +476,24 @@ def do_truncate(s, length=255, killwords=False, end='...'): result.append(end) return u' '.join(result) - -def do_wordwrap(s, width=79, break_long_words=True): +@environmentfilter +def do_wordwrap(environment, s, width=79, break_long_words=True, + wrapstring=None): """ Return a copy of the string passed to the filter wrapped after ``79`` characters. You can override this default using the first parameter. If you set the second parameter to `false` Jinja will not - split words apart if they are longer than `width`. + split words apart if they are longer than `width`. By default, the newlines + will be the default newlines for the environment, but this can be changed + using the wrapstring keyword argument. + + .. versionadded:: 2.7 + Added support for the `wrapstring` parameter. """ + if not wrapstring: + wrapstring = environment.newline_sequence import textwrap - return u'\n'.join(textwrap.wrap(s, width=width, expand_tabs=False, + return wrapstring.join(textwrap.wrap(s, width=width, expand_tabs=False, replace_whitespace=False, break_long_words=break_long_words)) @@ -456,7 +554,7 @@ def do_striptags(value): """ if hasattr(value, '__html__'): value = value.__html__() - return Markup(unicode(value)).striptags() + return Markup(text_type(value)).striptags() def do_slice(value, slices, fill_with=None): @@ -484,7 +582,7 @@ def do_slice(value, slices, fill_with=None): items_per_slice = length // slices slices_with_extra = length % slices offset = 0 - for slice_number in xrange(slices): + for slice_number in range(slices): start = offset + slice_number * items_per_slice if slice_number < slices_with_extra: offset += 1 @@ -500,7 +598,7 @@ def do_batch(value, linecount, fill_with=None): A filter that batches items. It works pretty much like `slice` just the other way round. It returns a list of lists with the given number of items. If you provide a second parameter this - is used to fill missing items. See this example: + is used to fill up missing items. See this example: .. sourcecode:: html+jinja @@ -595,8 +693,12 @@ def do_groupby(environment, value, attribute): As you can see the item we're grouping by is stored in the `grouper` attribute and the `list` contains all the objects that have this grouper in common. + + .. versionchanged:: 2.6 + It's now possible to use dotted notation to group by the child + attribute of another attribute. """ - expr = lambda x: environment.getitem(x, attribute) + expr = make_attrgetter(environment, attribute) return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr))) @@ -605,10 +707,32 @@ class _GroupTuple(tuple): grouper = property(itemgetter(0)) list = property(itemgetter(1)) - def __new__(cls, (key, value)): + def __new__(cls, xxx_todo_changeme): + (key, value) = xxx_todo_changeme return tuple.__new__(cls, (key, list(value))) +@environmentfilter +def do_sum(environment, iterable, attribute=None, start=0): + """Returns the sum of a sequence of numbers plus the value of parameter + 'start' (which defaults to 0). When the sequence is empty it returns + start. + + It is also possible to sum up only certain attributes: + + .. sourcecode:: jinja + + Total: {{ items|sum(attribute='price') }} + + .. versionchanged:: 2.6 + The `attribute` parameter was added to allow suming up over + attributes. Also the `start` parameter was moved on to the right. + """ + if attribute is not None: + iterable = imap(make_attrgetter(environment, attribute), iterable) + return sum(iterable, start) + + def do_list(value): """Convert the value into a list. If it was a string the returned list will be a list of characters. @@ -625,14 +749,14 @@ def do_mark_safe(value): def do_mark_unsafe(value): """Mark a value as unsafe. This is the reverse operation for :func:`safe`.""" - return unicode(value) + return text_type(value) def do_reverse(value): """Reverse the object or return an iterator the iterates over it the other way round. """ - if isinstance(value, basestring): + if isinstance(value, string_types): return value[::-1] try: return reversed(value) @@ -670,6 +794,144 @@ def do_attr(environment, obj, name): return environment.undefined(obj=obj, name=name) +@contextfilter +def do_map(*args, **kwargs): + """Applies a filter on a sequence of objects or looks up an attribute. + This is useful when dealing with lists of objects but you are really + only interested in a certain value of it. + + The basic usage is mapping on an attribute. Imagine you have a list + of users but you are only interested in a list of usernames: + + .. sourcecode:: jinja + + Users on this page: {{ users|map(attribute='username')|join(', ') }} + + Alternatively you can let it invoke a filter by passing the name of the + filter and the arguments afterwards. A good example would be applying a + text conversion filter on a sequence: + + .. sourcecode:: jinja + + Users on this page: {{ titles|map('lower')|join(', ') }} + + .. versionadded:: 2.7 + """ + context = args[0] + seq = args[1] + + if len(args) == 2 and 'attribute' in kwargs: + attribute = kwargs.pop('attribute') + if kwargs: + raise FilterArgumentError('Unexpected keyword argument %r' % + next(iter(kwargs))) + func = make_attrgetter(context.environment, attribute) + else: + try: + name = args[2] + args = args[3:] + except LookupError: + raise FilterArgumentError('map requires a filter argument') + func = lambda item: context.environment.call_filter( + name, item, args, kwargs, context=context) + + if seq: + for item in seq: + yield func(item) + + +@contextfilter +def do_select(*args, **kwargs): + """Filters a sequence of objects by appying a test to either the object + or the attribute and only selecting the ones with the test succeeding. + + Example usage: + + .. sourcecode:: jinja + + {{ numbers|select("odd") }} + + .. versionadded:: 2.7 + """ + return _select_or_reject(args, kwargs, lambda x: x, False) + + +@contextfilter +def do_reject(*args, **kwargs): + """Filters a sequence of objects by appying a test to either the object + or the attribute and rejecting the ones with the test succeeding. + + Example usage: + + .. sourcecode:: jinja + + {{ numbers|reject("odd") }} + + .. versionadded:: 2.7 + """ + return _select_or_reject(args, kwargs, lambda x: not x, False) + + +@contextfilter +def do_selectattr(*args, **kwargs): + """Filters a sequence of objects by appying a test to either the object + or the attribute and only selecting the ones with the test succeeding. + + Example usage: + + .. sourcecode:: jinja + + {{ users|selectattr("is_active") }} + {{ users|selectattr("email", "none") }} + + .. versionadded:: 2.7 + """ + return _select_or_reject(args, kwargs, lambda x: x, True) + + +@contextfilter +def do_rejectattr(*args, **kwargs): + """Filters a sequence of objects by appying a test to either the object + or the attribute and rejecting the ones with the test succeeding. + + .. sourcecode:: jinja + + {{ users|rejectattr("is_active") }} + {{ users|rejectattr("email", "none") }} + + .. versionadded:: 2.7 + """ + return _select_or_reject(args, kwargs, lambda x: not x, True) + + +def _select_or_reject(args, kwargs, modfunc, lookup_attr): + context = args[0] + seq = args[1] + if lookup_attr: + try: + attr = args[2] + except LookupError: + raise FilterArgumentError('Missing parameter for attribute name') + transfunc = make_attrgetter(context.environment, attr) + off = 1 + else: + off = 0 + transfunc = lambda x: x + + try: + name = args[2 + off] + args = args[3 + off:] + func = lambda item: context.environment.call_test( + name, item, args, kwargs) + except LookupError: + func = bool + + if seq: + for item in seq: + if modfunc(func(transfunc(item))): + yield item + + FILTERS = { 'attr': do_attr, 'replace': do_replace, @@ -694,7 +956,10 @@ FILTERS = { 'capitalize': do_capitalize, 'first': do_first, 'last': do_last, + 'map': do_map, 'random': do_random, + 'reject': do_reject, + 'rejectattr': do_rejectattr, 'filesizeformat': do_filesizeformat, 'pprint': do_pprint, 'truncate': do_truncate, @@ -708,12 +973,15 @@ FILTERS = { 'format': do_format, 'trim': do_trim, 'striptags': do_striptags, + 'select': do_select, + 'selectattr': do_selectattr, 'slice': do_slice, 'batch': do_batch, - 'sum': sum, + 'sum': do_sum, 'abs': abs, 'round': do_round, 'groupby': do_groupby, 'safe': do_mark_safe, - 'xmlattr': do_xmlattr + 'xmlattr': do_xmlattr, + 'urlencode': do_urlencode } diff --git a/module/lib/jinja2/lexer.py b/module/lib/jinja2/lexer.py index 0d3f69617..a50128507 100644 --- a/module/lib/jinja2/lexer.py +++ b/module/lib/jinja2/lexer.py @@ -15,10 +15,13 @@ :license: BSD, see LICENSE for more details. """ import re + from operator import itemgetter from collections import deque from jinja2.exceptions import TemplateSyntaxError -from jinja2.utils import LRUCache, next +from jinja2.utils import LRUCache +from jinja2._compat import next, iteritems, implements_iterator, text_type, \ + intern # cache for the lexers. Exists in order to be able to have multiple @@ -126,7 +129,7 @@ operators = { ';': TOKEN_SEMICOLON } -reverse_operators = dict([(v, k) for k, v in operators.iteritems()]) +reverse_operators = dict([(v, k) for k, v in iteritems(operators)]) assert len(operators) == len(reverse_operators), 'operators dropped' operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in sorted(operators, key=lambda x: -len(x)))) @@ -197,7 +200,7 @@ def compile_rules(environment): if environment.line_statement_prefix is not None: rules.append((len(environment.line_statement_prefix), 'linestatement', - r'^\s*' + e(environment.line_statement_prefix))) + r'^[ \t\v]*' + e(environment.line_statement_prefix))) if environment.line_comment_prefix is not None: rules.append((len(environment.line_comment_prefix), 'linecomment', r'(?:^|(?<=\S))[^\S\r\n]*' + @@ -262,6 +265,7 @@ class Token(tuple): ) +@implements_iterator class TokenStreamIterator(object): """The iterator for tokenstreams. Iterate over the stream until the eof token is reached. @@ -273,7 +277,7 @@ class TokenStreamIterator(object): def __iter__(self): return self - def next(self): + def __next__(self): token = self.stream.current if token.type is TOKEN_EOF: self.stream.close() @@ -282,6 +286,7 @@ class TokenStreamIterator(object): return token +@implements_iterator class TokenStream(object): """A token stream is an iterable that yields :class:`Token`\s. The parser however does not iterate over it but calls :meth:`next` to go @@ -289,7 +294,7 @@ class TokenStream(object): """ def __init__(self, generator, name, filename): - self._next = iter(generator).next + self._iter = iter(generator) self._pushed = deque() self.name = name self.filename = filename @@ -300,8 +305,9 @@ class TokenStream(object): def __iter__(self): return TokenStreamIterator(self) - def __nonzero__(self): + def __bool__(self): return bool(self._pushed) or self.current.type is not TOKEN_EOF + __nonzero__ = __bool__ # py2 eos = property(lambda x: not x, doc="Are we at the end of the stream?") @@ -319,7 +325,7 @@ class TokenStream(object): def skip(self, n=1): """Got n tokens ahead.""" - for x in xrange(n): + for x in range(n): next(self) def next_if(self, expr): @@ -333,14 +339,14 @@ class TokenStream(object): """Like :meth:`next_if` but only returns `True` or `False`.""" return self.next_if(expr) is not None - def next(self): + def __next__(self): """Go one token ahead and return the old one""" rv = self.current if self._pushed: self.current = self._pushed.popleft() elif self.current.type is not TOKEN_EOF: try: - self.current = self._next() + self.current = next(self._iter) except StopIteration: self.close() return rv @@ -348,7 +354,7 @@ class TokenStream(object): def close(self): """Close the stream.""" self.current = Token(self.current.lineno, TOKEN_EOF, '') - self._next = None + self._iter = None self.closed = True def expect(self, expr): @@ -383,7 +389,9 @@ def get_lexer(environment): environment.line_statement_prefix, environment.line_comment_prefix, environment.trim_blocks, - environment.newline_sequence) + environment.lstrip_blocks, + environment.newline_sequence, + environment.keep_trailing_newline) lexer = _lexer_cache.get(key) if lexer is None: lexer = Lexer(environment) @@ -414,7 +422,7 @@ class Lexer(object): (operator_re, TOKEN_OPERATOR, None) ] - # assamble the root lexing rule. because "|" is ungreedy + # assemble the root lexing rule. because "|" is ungreedy # we have to sort by length so that the lexer continues working # as expected when we have parsing rules like <% for block and # <%= for variables. (if someone wants asp like syntax) @@ -425,7 +433,44 @@ class Lexer(object): # block suffix if trimming is enabled block_suffix_re = environment.trim_blocks and '\\n?' or '' + # strip leading spaces if lstrip_blocks is enabled + prefix_re = {} + if environment.lstrip_blocks: + # use '{%+' to manually disable lstrip_blocks behavior + no_lstrip_re = e('+') + # detect overlap between block and variable or comment strings + block_diff = c(r'^%s(.*)' % e(environment.block_start_string)) + # make sure we don't mistake a block for a variable or a comment + m = block_diff.match(environment.comment_start_string) + no_lstrip_re += m and r'|%s' % e(m.group(1)) or '' + m = block_diff.match(environment.variable_start_string) + no_lstrip_re += m and r'|%s' % e(m.group(1)) or '' + + # detect overlap between comment and variable strings + comment_diff = c(r'^%s(.*)' % e(environment.comment_start_string)) + m = comment_diff.match(environment.variable_start_string) + no_variable_re = m and r'(?!%s)' % e(m.group(1)) or '' + + lstrip_re = r'^[ \t]*' + block_prefix_re = r'%s%s(?!%s)|%s\+?' % ( + lstrip_re, + e(environment.block_start_string), + no_lstrip_re, + e(environment.block_start_string), + ) + comment_prefix_re = r'%s%s%s|%s\+?' % ( + lstrip_re, + e(environment.comment_start_string), + no_variable_re, + e(environment.comment_start_string), + ) + prefix_re['block'] = block_prefix_re + prefix_re['comment'] = comment_prefix_re + else: + block_prefix_re = '%s' % e(environment.block_start_string) + self.newline_sequence = environment.newline_sequence + self.keep_trailing_newline = environment.keep_trailing_newline # global lexing rules self.rules = { @@ -434,11 +479,11 @@ class Lexer(object): (c('(.*?)(?:%s)' % '|'.join( [r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % ( e(environment.block_start_string), - e(environment.block_start_string), + block_prefix_re, e(environment.block_end_string), e(environment.block_end_string) )] + [ - r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, r) + r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, prefix_re.get(n,r)) for n, r in root_tag_rules ])), (TOKEN_DATA, '#bygroup'), '#bygroup'), # data @@ -472,7 +517,7 @@ class Lexer(object): TOKEN_RAW_BEGIN: [ (c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % ( e(environment.block_start_string), - e(environment.block_start_string), + block_prefix_re, e(environment.block_end_string), e(environment.block_end_string), block_suffix_re @@ -491,7 +536,7 @@ class Lexer(object): } def _normalize_newlines(self, value): - """Called for strings and template data to normlize it to unicode.""" + """Called for strings and template data to normalize it to unicode.""" return newline_re.sub(self.newline_sequence, value) def tokenize(self, source, name=None, filename=None, state=None): @@ -526,7 +571,7 @@ class Lexer(object): value = self._normalize_newlines(value[1:-1]) \ .encode('ascii', 'backslashreplace') \ .decode('unicode-escape') - except Exception, e: + except Exception as e: msg = str(e).split(':')[-1].strip() raise TemplateSyntaxError(msg, lineno, name, filename) # if we can express it as bytestring (ascii only) @@ -549,7 +594,14 @@ class Lexer(object): """This method tokenizes the text and returns the tokens in a generator. Use this method if you just want to tokenize a template. """ - source = '\n'.join(unicode(source).splitlines()) + source = text_type(source) + lines = source.splitlines() + if self.keep_trailing_newline and source: + for newline in ('\r\n', '\r', '\n'): + if source.endswith(newline): + lines.append('') + break + source = '\n'.join(lines) pos = 0 lineno = 1 stack = ['root'] @@ -571,7 +623,7 @@ class Lexer(object): if m is None: continue - # we only match blocks and variables if brances / parentheses + # we only match blocks and variables if braces / parentheses # are balanced. continue parsing with the lower rule which # is the operator rule. do this only if the end tags look # like operators @@ -590,7 +642,7 @@ class Lexer(object): # yield for the current token the first named # group that matched elif token == '#bygroup': - for key, value in m.groupdict().iteritems(): + for key, value in iteritems(m.groupdict()): if value is not None: yield lineno, key, value lineno += value.count('\n') @@ -647,7 +699,7 @@ class Lexer(object): stack.pop() # resolve the new state by group checking elif new_state == '#bygroup': - for key, value in m.groupdict().iteritems(): + for key, value in iteritems(m.groupdict()): if value is not None: stack.append(key) break @@ -669,7 +721,7 @@ class Lexer(object): # publish new function and start again pos = pos2 break - # if loop terminated without break we havn't found a single match + # if loop terminated without break we haven't found a single match # either we are at the end of the file or we have a problem else: # end of text diff --git a/module/lib/jinja2/loaders.py b/module/lib/jinja2/loaders.py index bd435e8b0..cc9c6836e 100644 --- a/module/lib/jinja2/loaders.py +++ b/module/lib/jinja2/loaders.py @@ -13,12 +13,10 @@ import sys import weakref from types import ModuleType from os import path -try: - from hashlib import sha1 -except ImportError: - from sha import new as sha1 +from hashlib import sha1 from jinja2.exceptions import TemplateNotFound -from jinja2.utils import LRUCache, open_if_exists, internalcode +from jinja2.utils import open_if_exists, internalcode +from jinja2._compat import string_types, iteritems def split_template_path(template): @@ -153,7 +151,7 @@ class FileSystemLoader(BaseLoader): """ def __init__(self, searchpath, encoding='utf-8'): - if isinstance(searchpath, basestring): + if isinstance(searchpath, string_types): searchpath = [searchpath] self.searchpath = list(searchpath) self.encoding = encoding @@ -251,8 +249,7 @@ class PackageLoader(BaseLoader): for filename in self.provider.resource_listdir(path): fullname = path + '/' + filename if self.provider.resource_isdir(fullname): - for item in _walk(fullname): - results.append(item) + _walk(fullname) else: results.append(fullname[offset:].lstrip('/')) _walk(path) @@ -275,7 +272,7 @@ class DictLoader(BaseLoader): def get_source(self, environment, template): if template in self.mapping: source = self.mapping[template] - return source, None, lambda: source != self.mapping.get(template) + return source, None, lambda: source == self.mapping.get(template) raise TemplateNotFound(template) def list_templates(self): @@ -307,7 +304,7 @@ class FunctionLoader(BaseLoader): rv = self.load_func(template) if rv is None: raise TemplateNotFound(template) - elif isinstance(rv, basestring): + elif isinstance(rv, string_types): return rv, None, None return rv @@ -331,12 +328,16 @@ class PrefixLoader(BaseLoader): self.mapping = mapping self.delimiter = delimiter - def get_source(self, environment, template): + def get_loader(self, template): try: prefix, name = template.split(self.delimiter, 1) loader = self.mapping[prefix] except (ValueError, KeyError): raise TemplateNotFound(template) + return loader, name + + def get_source(self, environment, template): + loader, name = self.get_loader(template) try: return loader.get_source(environment, name) except TemplateNotFound: @@ -344,9 +345,19 @@ class PrefixLoader(BaseLoader): # (the one that includes the prefix) raise TemplateNotFound(template) + @internalcode + def load(self, environment, name, globals=None): + loader, local_name = self.get_loader(name) + try: + return loader.load(environment, local_name, globals) + except TemplateNotFound: + # re-raise the exception with the correct fileame here. + # (the one that includes the prefix) + raise TemplateNotFound(name) + def list_templates(self): result = [] - for prefix, loader in self.mapping.iteritems(): + for prefix, loader in iteritems(self.mapping): for template in loader.list_templates(): result.append(prefix + self.delimiter + template) return result @@ -377,6 +388,15 @@ class ChoiceLoader(BaseLoader): pass raise TemplateNotFound(template) + @internalcode + def load(self, environment, name, globals=None): + for loader in self.loaders: + try: + return loader.load(environment, name, globals) + except TemplateNotFound: + pass + raise TemplateNotFound(name) + def list_templates(self): found = set() for loader in self.loaders: @@ -397,6 +417,8 @@ class ModuleLoader(BaseLoader): ... ModuleLoader('/path/to/compiled/templates'), ... FileSystemLoader('/path/to/templates') ... ]) + + Templates can be precompiled with :meth:`Environment.compile_templates`. """ has_source_access = False @@ -407,7 +429,7 @@ class ModuleLoader(BaseLoader): # create a fake module that looks for the templates in the # path given. mod = _TemplateModule(package_name) - if isinstance(path, basestring): + if isinstance(path, string_types): path = [path] else: path = list(path) diff --git a/module/lib/jinja2/meta.py b/module/lib/jinja2/meta.py index 3a779a5e9..3110cff60 100644 --- a/module/lib/jinja2/meta.py +++ b/module/lib/jinja2/meta.py @@ -11,6 +11,7 @@ """ from jinja2 import nodes from jinja2.compiler import CodeGenerator +from jinja2._compat import string_types class TrackingCodeGenerator(CodeGenerator): @@ -77,7 +78,7 @@ def find_referenced_templates(ast): # something const, only yield the strings and ignore # non-string consts that really just make no sense if isinstance(template_name, nodes.Const): - if isinstance(template_name.value, basestring): + if isinstance(template_name.value, string_types): yield template_name.value # something dynamic in there else: @@ -87,7 +88,7 @@ def find_referenced_templates(ast): yield None continue # constant is a basestring, direct template name - if isinstance(node.template.value, basestring): + if isinstance(node.template.value, string_types): yield node.template.value # a tuple or list (latter *should* not happen) made of consts, # yield the consts that are strings. We could warn here for @@ -95,7 +96,7 @@ def find_referenced_templates(ast): elif isinstance(node, nodes.Include) and \ isinstance(node.template.value, (tuple, list)): for template_name in node.template.value: - if isinstance(template_name, basestring): + if isinstance(template_name, string_types): yield template_name # something else we don't care about, we could warn here else: diff --git a/module/lib/jinja2/nodes.py b/module/lib/jinja2/nodes.py index 6446c70ea..c5697e6b5 100644 --- a/module/lib/jinja2/nodes.py +++ b/module/lib/jinja2/nodes.py @@ -13,13 +13,15 @@ :license: BSD, see LICENSE for more details. """ import operator -from itertools import chain, izip + from collections import deque -from jinja2.utils import Markup, MethodType, FunctionType +from jinja2.utils import Markup +from jinja2._compat import next, izip, with_metaclass, text_type, \ + method_type, function_type #: the types we support for context functions -_context_function_types = (FunctionType, MethodType) +_context_function_types = (function_type, method_type) _binop_to_func = { @@ -77,6 +79,7 @@ class EvalContext(object): """ def __init__(self, environment, template_name=None): + self.environment = environment if callable(environment.autoescape): self.autoescape = environment.autoescape(template_name) else: @@ -101,9 +104,9 @@ def get_eval_context(node, ctx): return ctx -class Node(object): +class Node(with_metaclass(NodeType, object)): """Baseclass for all Jinja2 nodes. There are a number of nodes available - of different types. There are three major types: + of different types. There are four major types: - :class:`Stmt`: statements - :class:`Expr`: expressions @@ -117,7 +120,6 @@ class Node(object): The `environment` attribute is set at the end of the parsing process for all nodes automatically. """ - __metaclass__ = NodeType fields = () attributes = ('lineno', 'environment') abstract = True @@ -141,7 +143,7 @@ class Node(object): setattr(self, attr, attributes.pop(attr, None)) if attributes: raise TypeError('unknown attribute %r' % - iter(attributes).next()) + next(iter(attributes))) def iter_fields(self, exclude=None, only=None): """This method iterates over all fields that are defined and yields @@ -230,6 +232,9 @@ class Node(object): def __ne__(self, other): return not self.__eq__(other) + # Restore Python 2 hashing behavior on Python 3 + __hash__ = object.__hash__ + def __repr__(self): return '%s(%s)' % ( self.__class__.__name__, @@ -372,10 +377,14 @@ class BinExpr(Expr): def as_const(self, eval_ctx=None): eval_ctx = get_eval_context(self, eval_ctx) + # intercepted operators cannot be folded at compile time + if self.environment.sandboxed and \ + self.operator in self.environment.intercepted_binops: + raise Impossible() f = _binop_to_func[self.operator] try: return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx)) - except: + except Exception: raise Impossible() @@ -387,10 +396,14 @@ class UnaryExpr(Expr): def as_const(self, eval_ctx=None): eval_ctx = get_eval_context(self, eval_ctx) + # intercepted operators cannot be folded at compile time + if self.environment.sandboxed and \ + self.operator in self.environment.intercepted_unops: + raise Impossible() f = _uaop_to_func[self.operator] try: return f(self.node.as_const(eval_ctx)) - except: + except Exception: raise Impossible() @@ -431,7 +444,7 @@ class Const(Literal): constant value in the generated code, otherwise it will raise an `Impossible` exception. """ - from compiler import has_safe_repr + from .compiler import has_safe_repr if not has_safe_repr(value): raise Impossible() return cls(value, lineno=lineno, environment=environment) @@ -555,16 +568,16 @@ class Filter(Expr): if self.dyn_args is not None: try: args.extend(self.dyn_args.as_const(eval_ctx)) - except: + except Exception: raise Impossible() if self.dyn_kwargs is not None: try: kwargs.update(self.dyn_kwargs.as_const(eval_ctx)) - except: + except Exception: raise Impossible() try: return filter_(obj, *args, **kwargs) - except: + except Exception: raise Impossible() @@ -604,16 +617,16 @@ class Call(Expr): if self.dyn_args is not None: try: args.extend(self.dyn_args.as_const(eval_ctx)) - except: + except Exception: raise Impossible() if self.dyn_kwargs is not None: try: kwargs.update(self.dyn_kwargs.as_const(eval_ctx)) - except: + except Exception: raise Impossible() try: return obj(*args, **kwargs) - except: + except Exception: raise Impossible() @@ -628,7 +641,7 @@ class Getitem(Expr): try: return self.environment.getitem(self.node.as_const(eval_ctx), self.arg.as_const(eval_ctx)) - except: + except Exception: raise Impossible() def can_assign(self): @@ -648,7 +661,7 @@ class Getattr(Expr): eval_ctx = get_eval_context(self, eval_ctx) return self.environment.getattr(self.node.as_const(eval_ctx), self.attr) - except: + except Exception: raise Impossible() def can_assign(self): @@ -678,7 +691,7 @@ class Concat(Expr): def as_const(self, eval_ctx=None): eval_ctx = get_eval_context(self, eval_ctx) - return ''.join(unicode(x.as_const(eval_ctx)) for x in self.nodes) + return ''.join(text_type(x.as_const(eval_ctx)) for x in self.nodes) class Compare(Expr): @@ -695,7 +708,7 @@ class Compare(Expr): new_value = op.expr.as_const(eval_ctx) result = _cmpop_to_func[op.op](value, new_value) value = new_value - except: + except Exception: raise Impossible() return result diff --git a/module/lib/jinja2/parser.py b/module/lib/jinja2/parser.py index d44229ad0..f60cd018c 100644 --- a/module/lib/jinja2/parser.py +++ b/module/lib/jinja2/parser.py @@ -10,8 +10,8 @@ """ from jinja2 import nodes from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError -from jinja2.utils import next from jinja2.lexer import describe_token, describe_token_expr +from jinja2._compat import next, imap #: statements that callinto @@ -53,7 +53,7 @@ class Parser(object): def _fail_ut_eof(self, name, end_token_stack, lineno): expected = [] for exprs in end_token_stack: - expected.extend(map(describe_token_expr, exprs)) + expected.extend(imap(describe_token_expr, exprs)) if end_token_stack: currently_looking = ' or '.join( "'%s'" % describe_token_expr(expr) @@ -223,7 +223,7 @@ class Parser(object): # raise a nicer error message in that case. if self.stream.current.type == 'sub': self.fail('Block names in Jinja have to be valid Python ' - 'identifiers and may not contain hypens, use an ' + 'identifiers and may not contain hyphens, use an ' 'underscore instead.') node.body = self.parse_statements(('name:endblock',), drop_needle=True) @@ -698,7 +698,6 @@ class Parser(object): arg = nodes.Const(attr_token.value, lineno=attr_token.lineno) return nodes.Getitem(node, arg, 'load', lineno=token.lineno) if token.type == 'lbracket': - priority_on_attribute = False args = [] while self.stream.current.type != 'rbracket': if args: diff --git a/module/lib/jinja2/runtime.py b/module/lib/jinja2/runtime.py index 6fea3aa4f..7791c645a 100644 --- a/module/lib/jinja2/runtime.py +++ b/module/lib/jinja2/runtime.py @@ -8,13 +8,14 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD. """ -import sys -from itertools import chain, imap +from itertools import chain from jinja2.nodes import EvalContext, _context_function_types -from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \ - concat, internalcode, next, object_type_repr +from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \ + internalcode, object_type_repr from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \ TemplateNotFound +from jinja2._compat import next, imap, text_type, iteritems, \ + implements_iterator, implements_to_string, string_types, PY2 # these variables are exported to the template runtime @@ -24,13 +25,14 @@ __all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup', 'TemplateNotFound'] #: the name of the function that is used to convert something into -#: a string. 2to3 will adopt that automatically and the generated -#: code can take advantage of it. -to_string = unicode +#: a string. We can just use the text type here. +to_string = text_type #: the identity function. Useful for certain things in the environment identity = lambda x: x +_last_iteration = object() + def markup_join(seq): """Concatenation that escapes if necessary and converts to unicode.""" @@ -45,7 +47,7 @@ def markup_join(seq): def unicode_join(seq): """Simple args to unicode conversion and concatenation.""" - return concat(imap(unicode, seq)) + return concat(imap(text_type, seq)) def new_context(environment, template_name, blocks, vars=None, @@ -62,7 +64,7 @@ def new_context(environment, template_name, blocks, vars=None, # we don't want to modify the dict passed if shared: parent = dict(parent) - for key, value in locals.iteritems(): + for key, value in iteritems(locals): if key[:2] == 'l_' and value is not missing: parent[key[2:]] = value return Context(environment, parent, template_name, blocks) @@ -76,8 +78,6 @@ class TemplateReference(object): def __getitem__(self, name): blocks = self.__context.blocks[name] - wrap = self.__context.eval_ctx.autoescape and \ - Markup or (lambda x: x) return BlockReference(name, self.__context, blocks, 0) def __repr__(self): @@ -120,7 +120,7 @@ class Context(object): # create the initial mapping of blocks. Whenever template inheritance # takes place the runtime will update this mapping with the new blocks # from the template. - self.blocks = dict((k, [v]) for k, v in blocks.iteritems()) + self.blocks = dict((k, [v]) for k, v in iteritems(blocks)) def super(self, name, current): """Render a parent block.""" @@ -172,6 +172,16 @@ class Context(object): """ if __debug__: __traceback_hide__ = True + + # Allow callable classes to take a context + fn = __obj.__call__ + for fn_type in ('contextfunction', + 'evalcontextfunction', + 'environmentfunction'): + if hasattr(fn, fn_type): + __obj = fn + break + if isinstance(__obj, _context_function_types): if getattr(__obj, 'contextfunction', 0): args = (__self,) + args @@ -190,8 +200,9 @@ class Context(object): """Internal helper function to create a derived context.""" context = new_context(self.environment, self.name, {}, self.parent, True, None, locals) + context.vars.update(self.vars) context.eval_ctx = self.eval_ctx - context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems()) + context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks)) return context def _all(meth): @@ -205,7 +216,7 @@ class Context(object): items = _all('items') # not available on python 3 - if hasattr(dict, 'iterkeys'): + if PY2: iterkeys = _all('iterkeys') itervalues = _all('itervalues') iteritems = _all('iteritems') @@ -269,10 +280,12 @@ class BlockReference(object): class LoopContext(object): """A loop context for dynamic iteration.""" - def __init__(self, iterable, recurse=None): + def __init__(self, iterable, recurse=None, depth0=0): self._iterator = iter(iterable) self._recurse = recurse + self._after = self._safe_next() self.index0 = -1 + self.depth0 = depth0 # try to get the length of the iterable early. This must be done # here because there are some broken iterators around where there @@ -290,10 +303,11 @@ class LoopContext(object): return args[self.index0 % len(args)] first = property(lambda x: x.index0 == 0) - last = property(lambda x: x.index0 + 1 == x.length) + last = property(lambda x: x._after is _last_iteration) index = property(lambda x: x.index0 + 1) revindex = property(lambda x: x.length - x.index0) revindex0 = property(lambda x: x.length - x.index) + depth = property(lambda x: x.depth0 + 1) def __len__(self): return self.length @@ -301,12 +315,18 @@ class LoopContext(object): def __iter__(self): return LoopContextIterator(self) + def _safe_next(self): + try: + return next(self._iterator) + except StopIteration: + return _last_iteration + @internalcode def loop(self, iterable): if self._recurse is None: raise TypeError('Tried to call non recursive loop. Maybe you ' "forgot the 'recursive' modifier.") - return self._recurse(iterable, self._recurse) + return self._recurse(iterable, self._recurse, self.depth0 + 1) # a nifty trick to enhance the error message if someone tried to call # the the loop without or with too many arguments. @@ -333,6 +353,7 @@ class LoopContext(object): ) +@implements_iterator class LoopContextIterator(object): """The iterator for a loop context.""" __slots__ = ('context',) @@ -343,10 +364,14 @@ class LoopContextIterator(object): def __iter__(self): return self - def next(self): + def __next__(self): ctx = self.context ctx.index0 += 1 - return next(ctx._iterator), ctx + if ctx._after is _last_iteration: + raise StopIteration() + next_elem = ctx._after + ctx._after = ctx._safe_next() + return next_elem, ctx class Macro(object): @@ -413,6 +438,7 @@ class Macro(object): ) +@implements_to_string class Undefined(object): """The default undefined type. This undefined type can be printed and iterated over, but every other access will raise an :exc:`UndefinedError`: @@ -444,7 +470,7 @@ class Undefined(object): if self._undefined_hint is None: if self._undefined_obj is missing: hint = '%r is undefined' % self._undefined_name - elif not isinstance(self._undefined_name, basestring): + elif not isinstance(self._undefined_name, string_types): hint = '%s has no element %r' % ( object_type_repr(self._undefined_obj), self._undefined_name @@ -458,21 +484,29 @@ class Undefined(object): hint = self._undefined_hint raise self._undefined_exception(hint) + @internalcode + def __getattr__(self, name): + if name[:2] == '__': + raise AttributeError(name) + return self._fail_with_undefined_error() + __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \ __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \ __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \ - __getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \ - __int__ = __float__ = __complex__ = __pow__ = __rpow__ = \ + __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \ + __float__ = __complex__ = __pow__ = __rpow__ = \ _fail_with_undefined_error - def __str__(self): - return unicode(self).encode('utf-8') + def __eq__(self, other): + return type(self) is type(other) + + def __ne__(self, other): + return not self.__eq__(other) - # unicode goes after __str__ because we configured 2to3 to rename - # __unicode__ to __str__. because the 2to3 tree is not designed to - # remove nodes from it, we leave the above __str__ around and let - # it override at runtime. - def __unicode__(self): + def __hash__(self): + return id(type(self)) + + def __str__(self): return u'' def __len__(self): @@ -489,6 +523,7 @@ class Undefined(object): return 'Undefined' +@implements_to_string class DebugUndefined(Undefined): """An undefined that returns the debug info when printed. @@ -504,7 +539,7 @@ class DebugUndefined(Undefined): """ __slots__ = () - def __unicode__(self): + def __str__(self): if self._undefined_hint is None: if self._undefined_obj is missing: return u'{{ %s }}' % self._undefined_name @@ -515,6 +550,7 @@ class DebugUndefined(Undefined): return u'{{ undefined value printed: %s }}' % self._undefined_hint +@implements_to_string class StrictUndefined(Undefined): """An undefined that barks on print and iteration as well as boolean tests and all kinds of comparisons. In other words: you can do nothing @@ -535,8 +571,9 @@ class StrictUndefined(Undefined): UndefinedError: 'foo' is undefined """ __slots__ = () - __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \ - __ne__ = __bool__ = Undefined._fail_with_undefined_error + __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \ + __ne__ = __bool__ = __hash__ = \ + Undefined._fail_with_undefined_error # remove remaining slots attributes, after the metaclass did the magic they diff --git a/module/lib/jinja2/sandbox.py b/module/lib/jinja2/sandbox.py index 749719548..da479c1ba 100644 --- a/module/lib/jinja2/sandbox.py +++ b/module/lib/jinja2/sandbox.py @@ -13,11 +13,10 @@ :license: BSD. """ import operator -from jinja2.runtime import Undefined from jinja2.environment import Environment from jinja2.exceptions import SecurityError -from jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \ - FrameType, GeneratorType +from jinja2._compat import string_types, function_type, method_type, \ + traceback_type, code_type, frame_type, generator_type, PY2 #: maximum number of items a range may produce @@ -30,6 +29,13 @@ UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict', #: unsafe method attributes. function attributes are unsafe for methods too UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self']) +#: unsafe generator attirbutes. +UNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code']) + +# On versions > python 2 the special attributes on functions are gone, +# but they remain on methods and generators for whatever reason. +if not PY2: + UNSAFE_FUNCTION_ATTRIBUTES = set() import warnings @@ -91,7 +97,7 @@ def safe_range(*args): """A range that can't generate ranges with a length of more than MAX_RANGE items. """ - rng = xrange(*args) + rng = range(*args) if len(rng) > MAX_RANGE: raise OverflowError('range too big, maximum size for range is %d' % MAX_RANGE) @@ -99,8 +105,9 @@ def safe_range(*args): def unsafe(f): - """ - Mark a function or method as unsafe:: + """Marks a function or method as unsafe. + + :: @unsafe def delete(self): @@ -114,7 +121,7 @@ def is_internal_attribute(obj, attr): """Test if the attribute given is an internal python attribute. For example this function returns `True` for the `func_code` attribute of python objects. This is useful if the environment method - :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden. + :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden. >>> from jinja2.sandbox import is_internal_attribute >>> is_internal_attribute(lambda: None, "func_code") @@ -124,20 +131,20 @@ def is_internal_attribute(obj, attr): >>> is_internal_attribute(str, "upper") False """ - if isinstance(obj, FunctionType): + if isinstance(obj, function_type): if attr in UNSAFE_FUNCTION_ATTRIBUTES: return True - elif isinstance(obj, MethodType): + elif isinstance(obj, method_type): if attr in UNSAFE_FUNCTION_ATTRIBUTES or \ attr in UNSAFE_METHOD_ATTRIBUTES: return True elif isinstance(obj, type): if attr == 'mro': return True - elif isinstance(obj, (CodeType, TracebackType, FrameType)): + elif isinstance(obj, (code_type, traceback_type, frame_type)): return True - elif isinstance(obj, GeneratorType): - if attr == 'gi_frame': + elif isinstance(obj, generator_type): + if attr in UNSAFE_GENERATOR_ATTRIBUTES: return True return attr.startswith('__') @@ -182,9 +189,81 @@ class SandboxedEnvironment(Environment): """ sandboxed = True + #: default callback table for the binary operators. A copy of this is + #: available on each instance of a sandboxed environment as + #: :attr:`binop_table` + default_binop_table = { + '+': operator.add, + '-': operator.sub, + '*': operator.mul, + '/': operator.truediv, + '//': operator.floordiv, + '**': operator.pow, + '%': operator.mod + } + + #: default callback table for the unary operators. A copy of this is + #: available on each instance of a sandboxed environment as + #: :attr:`unop_table` + default_unop_table = { + '+': operator.pos, + '-': operator.neg + } + + #: a set of binary operators that should be intercepted. Each operator + #: that is added to this set (empty by default) is delegated to the + #: :meth:`call_binop` method that will perform the operator. The default + #: operator callback is specified by :attr:`binop_table`. + #: + #: The following binary operators are interceptable: + #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**`` + #: + #: The default operation form the operator table corresponds to the + #: builtin function. Intercepted calls are always slower than the native + #: operator call, so make sure only to intercept the ones you are + #: interested in. + #: + #: .. versionadded:: 2.6 + intercepted_binops = frozenset() + + #: a set of unary operators that should be intercepted. Each operator + #: that is added to this set (empty by default) is delegated to the + #: :meth:`call_unop` method that will perform the operator. The default + #: operator callback is specified by :attr:`unop_table`. + #: + #: The following unary operators are interceptable: ``+``, ``-`` + #: + #: The default operation form the operator table corresponds to the + #: builtin function. Intercepted calls are always slower than the native + #: operator call, so make sure only to intercept the ones you are + #: interested in. + #: + #: .. versionadded:: 2.6 + intercepted_unops = frozenset() + + def intercept_unop(self, operator): + """Called during template compilation with the name of a unary + operator to check if it should be intercepted at runtime. If this + method returns `True`, :meth:`call_unop` is excuted for this unary + operator. The default implementation of :meth:`call_unop` will use + the :attr:`unop_table` dictionary to perform the operator with the + same logic as the builtin one. + + The following unary operators are interceptable: ``+`` and ``-`` + + Intercepted calls are always slower than the native operator call, + so make sure only to intercept the ones you are interested in. + + .. versionadded:: 2.6 + """ + return False + + def __init__(self, *args, **kwargs): Environment.__init__(self, *args, **kwargs) self.globals['range'] = safe_range + self.binop_table = self.default_binop_table.copy() + self.unop_table = self.default_unop_table.copy() def is_safe_attribute(self, obj, attr, value): """The sandboxed environment will call this method to check if the @@ -201,18 +280,36 @@ class SandboxedEnvironment(Environment): True. Override this method to alter the behavior, but this won't affect the `unsafe` decorator from this module. """ - return not (getattr(obj, 'unsafe_callable', False) or \ + return not (getattr(obj, 'unsafe_callable', False) or getattr(obj, 'alters_data', False)) + def call_binop(self, context, operator, left, right): + """For intercepted binary operator calls (:meth:`intercepted_binops`) + this function is executed instead of the builtin operator. This can + be used to fine tune the behavior of certain operators. + + .. versionadded:: 2.6 + """ + return self.binop_table[operator](left, right) + + def call_unop(self, context, operator, arg): + """For intercepted unary operator calls (:meth:`intercepted_unops`) + this function is executed instead of the builtin operator. This can + be used to fine tune the behavior of certain operators. + + .. versionadded:: 2.6 + """ + return self.unop_table[operator](arg) + def getitem(self, obj, argument): """Subscribe an object from sandboxed code.""" try: return obj[argument] except (TypeError, LookupError): - if isinstance(argument, basestring): + if isinstance(argument, string_types): try: attr = str(argument) - except: + except Exception: pass else: try: diff --git a/module/lib/jinja2/tests.py b/module/lib/jinja2/tests.py index d257eca0a..48a3e0618 100644 --- a/module/lib/jinja2/tests.py +++ b/module/lib/jinja2/tests.py @@ -10,20 +10,14 @@ """ import re from jinja2.runtime import Undefined - -# nose, nothing here to test -__test__ = False +from jinja2._compat import text_type, string_types, mapping_types number_re = re.compile(r'^-?\d+(\.\d+)?$') regex_type = type(number_re) -try: - test_callable = callable -except NameError: - def test_callable(x): - return hasattr(x, '__call__') +test_callable = callable def test_odd(value): @@ -70,22 +64,30 @@ def test_none(value): def test_lower(value): """Return true if the variable is lowercased.""" - return unicode(value).islower() + return text_type(value).islower() def test_upper(value): """Return true if the variable is uppercased.""" - return unicode(value).isupper() + return text_type(value).isupper() def test_string(value): """Return true if the object is a string.""" - return isinstance(value, basestring) + return isinstance(value, string_types) + + +def test_mapping(value): + """Return true if the object is a mapping (dict etc.). + + .. versionadded:: 2.6 + """ + return isinstance(value, mapping_types) def test_number(value): """Return true if the variable is a number.""" - return isinstance(value, (int, long, float, complex)) + return isinstance(value, (int, float, complex)) def test_sequence(value): @@ -137,6 +139,7 @@ TESTS = { 'lower': test_lower, 'upper': test_upper, 'string': test_string, + 'mapping': test_mapping, 'number': test_number, 'sequence': test_sequence, 'iterable': test_iterable, diff --git a/module/lib/jinja2/testsuite/__init__.py b/module/lib/jinja2/testsuite/__init__.py new file mode 100644 index 000000000..635c83e5d --- /dev/null +++ b/module/lib/jinja2/testsuite/__init__.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite + ~~~~~~~~~~~~~~~~ + + All the unittests of Jinja2. These tests can be executed by + either running run-tests.py using multiple Python versions at + the same time. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import os +import re +import sys +import unittest +from traceback import format_exception +from jinja2 import loaders +from jinja2._compat import PY2 + + +here = os.path.dirname(os.path.abspath(__file__)) + +dict_loader = loaders.DictLoader({ + 'justdict.html': 'FOO' +}) +package_loader = loaders.PackageLoader('jinja2.testsuite.res', 'templates') +filesystem_loader = loaders.FileSystemLoader(here + '/res/templates') +function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get) +choice_loader = loaders.ChoiceLoader([dict_loader, package_loader]) +prefix_loader = loaders.PrefixLoader({ + 'a': filesystem_loader, + 'b': dict_loader +}) + + +class JinjaTestCase(unittest.TestCase): + + ### use only these methods for testing. If you need standard + ### unittest method, wrap them! + + def setup(self): + pass + + def teardown(self): + pass + + def setUp(self): + self.setup() + + def tearDown(self): + self.teardown() + + def assert_equal(self, a, b): + return self.assertEqual(a, b) + + def assert_raises(self, *args, **kwargs): + return self.assertRaises(*args, **kwargs) + + def assert_traceback_matches(self, callback, expected_tb): + try: + callback() + except Exception as e: + tb = format_exception(*sys.exc_info()) + if re.search(expected_tb.strip(), ''.join(tb)) is None: + raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s' + % (''.join(tb), expected_tb)) + else: + self.fail('Expected exception') + + +def find_all_tests(suite): + """Yields all the tests and their names from a given suite.""" + suites = [suite] + while suites: + s = suites.pop() + try: + suites.extend(s) + except TypeError: + yield s, '%s.%s.%s' % ( + s.__class__.__module__, + s.__class__.__name__, + s._testMethodName + ) + + +class BetterLoader(unittest.TestLoader): + """A nicer loader that solves two problems. First of all we are setting + up tests from different sources and we're doing this programmatically + which breaks the default loading logic so this is required anyways. + Secondly this loader has a nicer interpolation for test names than the + default one so you can just do ``run-tests.py ViewTestCase`` and it + will work. + """ + + def getRootSuite(self): + return suite() + + def loadTestsFromName(self, name, module=None): + root = self.getRootSuite() + if name == 'suite': + return root + + all_tests = [] + for testcase, testname in find_all_tests(root): + if testname == name or \ + testname.endswith('.' + name) or \ + ('.' + name + '.') in testname or \ + testname.startswith(name + '.'): + all_tests.append(testcase) + + if not all_tests: + raise LookupError('could not find test case for "%s"' % name) + + if len(all_tests) == 1: + return all_tests[0] + rv = unittest.TestSuite() + for test in all_tests: + rv.addTest(test) + return rv + + +def suite(): + from jinja2.testsuite import ext, filters, tests, core_tags, \ + loader, inheritance, imports, lexnparse, security, api, \ + regression, debug, utils, bytecode_cache, doctests + suite = unittest.TestSuite() + suite.addTest(ext.suite()) + suite.addTest(filters.suite()) + suite.addTest(tests.suite()) + suite.addTest(core_tags.suite()) + suite.addTest(loader.suite()) + suite.addTest(inheritance.suite()) + suite.addTest(imports.suite()) + suite.addTest(lexnparse.suite()) + suite.addTest(security.suite()) + suite.addTest(api.suite()) + suite.addTest(regression.suite()) + suite.addTest(debug.suite()) + suite.addTest(utils.suite()) + suite.addTest(bytecode_cache.suite()) + + # doctests will not run on python 3 currently. Too many issues + # with that, do not test that on that platform. + if PY2: + suite.addTest(doctests.suite()) + + return suite + + +def main(): + """Runs the testsuite as command line application.""" + try: + unittest.main(testLoader=BetterLoader(), defaultTest='suite') + except Exception as e: + print('Error: %s' % e) diff --git a/module/lib/jinja2/testsuite/api.py b/module/lib/jinja2/testsuite/api.py new file mode 100644 index 000000000..1b68bf8b3 --- /dev/null +++ b/module/lib/jinja2/testsuite/api.py @@ -0,0 +1,261 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.api + ~~~~~~~~~~~~~~~~~~~~ + + Tests the public API and related stuff. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest +import os +import tempfile +import shutil + +from jinja2.testsuite import JinjaTestCase +from jinja2._compat import next + +from jinja2 import Environment, Undefined, DebugUndefined, \ + StrictUndefined, UndefinedError, meta, \ + is_undefined, Template, DictLoader +from jinja2.utils import Cycler + +env = Environment() + + +class ExtendedAPITestCase(JinjaTestCase): + + def test_item_and_attribute(self): + from jinja2.sandbox import SandboxedEnvironment + + for env in Environment(), SandboxedEnvironment(): + # the |list is necessary for python3 + tmpl = env.from_string('{{ foo.items()|list }}') + assert tmpl.render(foo={'items': 42}) == "[('items', 42)]" + tmpl = env.from_string('{{ foo|attr("items")()|list }}') + assert tmpl.render(foo={'items': 42}) == "[('items', 42)]" + tmpl = env.from_string('{{ foo["items"] }}') + assert tmpl.render(foo={'items': 42}) == '42' + + def test_finalizer(self): + def finalize_none_empty(value): + if value is None: + value = u'' + return value + env = Environment(finalize=finalize_none_empty) + tmpl = env.from_string('{% for item in seq %}|{{ item }}{% endfor %}') + assert tmpl.render(seq=(None, 1, "foo")) == '||1|foo' + tmpl = env.from_string('<{{ none }}>') + assert tmpl.render() == '<>' + + def test_cycler(self): + items = 1, 2, 3 + c = Cycler(*items) + for item in items + items: + assert c.current == item + assert next(c) == item + next(c) + assert c.current == 2 + c.reset() + assert c.current == 1 + + def test_expressions(self): + expr = env.compile_expression("foo") + assert expr() is None + assert expr(foo=42) == 42 + expr2 = env.compile_expression("foo", undefined_to_none=False) + assert is_undefined(expr2()) + + expr = env.compile_expression("42 + foo") + assert expr(foo=42) == 84 + + def test_template_passthrough(self): + t = Template('Content') + assert env.get_template(t) is t + assert env.select_template([t]) is t + assert env.get_or_select_template([t]) is t + assert env.get_or_select_template(t) is t + + def test_autoescape_autoselect(self): + def select_autoescape(name): + if name is None or '.' not in name: + return False + return name.endswith('.html') + env = Environment(autoescape=select_autoescape, + loader=DictLoader({ + 'test.txt': '{{ foo }}', + 'test.html': '{{ foo }}' + })) + t = env.get_template('test.txt') + assert t.render(foo='<foo>') == '<foo>' + t = env.get_template('test.html') + assert t.render(foo='<foo>') == '<foo>' + t = env.from_string('{{ foo }}') + assert t.render(foo='<foo>') == '<foo>' + + +class MetaTestCase(JinjaTestCase): + + def test_find_undeclared_variables(self): + ast = env.parse('{% set foo = 42 %}{{ bar + foo }}') + x = meta.find_undeclared_variables(ast) + assert x == set(['bar']) + + ast = env.parse('{% set foo = 42 %}{{ bar + foo }}' + '{% macro meh(x) %}{{ x }}{% endmacro %}' + '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}') + x = meta.find_undeclared_variables(ast) + assert x == set(['bar', 'seq', 'muh']) + + def test_find_refererenced_templates(self): + ast = env.parse('{% extends "layout.html" %}{% include helper %}') + i = meta.find_referenced_templates(ast) + assert next(i) == 'layout.html' + assert next(i) is None + assert list(i) == [] + + ast = env.parse('{% extends "layout.html" %}' + '{% from "test.html" import a, b as c %}' + '{% import "meh.html" as meh %}' + '{% include "muh.html" %}') + i = meta.find_referenced_templates(ast) + assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html'] + + def test_find_included_templates(self): + ast = env.parse('{% include ["foo.html", "bar.html"] %}') + i = meta.find_referenced_templates(ast) + assert list(i) == ['foo.html', 'bar.html'] + + ast = env.parse('{% include ("foo.html", "bar.html") %}') + i = meta.find_referenced_templates(ast) + assert list(i) == ['foo.html', 'bar.html'] + + ast = env.parse('{% include ["foo.html", "bar.html", foo] %}') + i = meta.find_referenced_templates(ast) + assert list(i) == ['foo.html', 'bar.html', None] + + ast = env.parse('{% include ("foo.html", "bar.html", foo) %}') + i = meta.find_referenced_templates(ast) + assert list(i) == ['foo.html', 'bar.html', None] + + +class StreamingTestCase(JinjaTestCase): + + def test_basic_streaming(self): + tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index " + "}} - {{ item }}</li>{%- endfor %}</ul>") + stream = tmpl.stream(seq=list(range(4))) + self.assert_equal(next(stream), '<ul>') + self.assert_equal(next(stream), '<li>1 - 0</li>') + self.assert_equal(next(stream), '<li>2 - 1</li>') + self.assert_equal(next(stream), '<li>3 - 2</li>') + self.assert_equal(next(stream), '<li>4 - 3</li>') + self.assert_equal(next(stream), '</ul>') + + def test_buffered_streaming(self): + tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index " + "}} - {{ item }}</li>{%- endfor %}</ul>") + stream = tmpl.stream(seq=list(range(4))) + stream.enable_buffering(size=3) + self.assert_equal(next(stream), u'<ul><li>1 - 0</li><li>2 - 1</li>') + self.assert_equal(next(stream), u'<li>3 - 2</li><li>4 - 3</li></ul>') + + def test_streaming_behavior(self): + tmpl = env.from_string("") + stream = tmpl.stream() + assert not stream.buffered + stream.enable_buffering(20) + assert stream.buffered + stream.disable_buffering() + assert not stream.buffered + + def test_dump_stream(self): + tmp = tempfile.mkdtemp() + try: + tmpl = env.from_string(u"\u2713") + stream = tmpl.stream() + stream.dump(os.path.join(tmp, 'dump.txt'), 'utf-8') + with open(os.path.join(tmp, 'dump.txt'), 'rb') as f: + self.assertEqual(f.read(), b'\xe2\x9c\x93') + finally: + shutil.rmtree(tmp) + + +class UndefinedTestCase(JinjaTestCase): + + def test_stopiteration_is_undefined(self): + def test(): + raise StopIteration() + t = Template('A{{ test() }}B') + assert t.render(test=test) == 'AB' + t = Template('A{{ test().missingattribute }}B') + self.assert_raises(UndefinedError, t.render, test=test) + + def test_undefined_and_special_attributes(self): + try: + Undefined('Foo').__dict__ + except AttributeError: + pass + else: + assert False, "Expected actual attribute error" + + def test_default_undefined(self): + env = Environment(undefined=Undefined) + self.assert_equal(env.from_string('{{ missing }}').render(), u'') + self.assert_raises(UndefinedError, + env.from_string('{{ missing.attribute }}').render) + self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]') + self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True') + self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '') + self.assert_equal(env.from_string('{{ not missing }}').render(), 'True') + + def test_debug_undefined(self): + env = Environment(undefined=DebugUndefined) + self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}') + self.assert_raises(UndefinedError, + env.from_string('{{ missing.attribute }}').render) + self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]') + self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True') + self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), + u"{{ no such element: int object['missing'] }}") + self.assert_equal(env.from_string('{{ not missing }}').render(), 'True') + + def test_strict_undefined(self): + env = Environment(undefined=StrictUndefined) + self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render) + self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render) + self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render) + self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True') + self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42) + self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render) + self.assert_equal(env.from_string('{{ missing|default("default", true) }}').render(), 'default') + + def test_indexing_gives_undefined(self): + t = Template("{{ var[42].foo }}") + self.assert_raises(UndefinedError, t.render, var=0) + + def test_none_gives_proper_error(self): + try: + Environment().getattr(None, 'split')() + except UndefinedError as e: + assert e.message == "'None' has no attribute 'split'" + else: + assert False, 'expected exception' + + def test_object_repr(self): + try: + Undefined(obj=42, name='upper')() + except UndefinedError as e: + assert e.message == "'int object' has no attribute 'upper'" + else: + assert False, 'expected exception' + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(ExtendedAPITestCase)) + suite.addTest(unittest.makeSuite(MetaTestCase)) + suite.addTest(unittest.makeSuite(StreamingTestCase)) + suite.addTest(unittest.makeSuite(UndefinedTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/bytecode_cache.py b/module/lib/jinja2/testsuite/bytecode_cache.py new file mode 100644 index 000000000..9f5c635b8 --- /dev/null +++ b/module/lib/jinja2/testsuite/bytecode_cache.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.bytecode_cache + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Test bytecode caching + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase, package_loader + +from jinja2 import Environment +from jinja2.bccache import FileSystemBytecodeCache +from jinja2.exceptions import TemplateNotFound + +bytecode_cache = FileSystemBytecodeCache() +env = Environment( + loader=package_loader, + bytecode_cache=bytecode_cache, +) + + +class ByteCodeCacheTestCase(JinjaTestCase): + + def test_simple(self): + tmpl = env.get_template('test.html') + assert tmpl.render().strip() == 'BAR' + self.assert_raises(TemplateNotFound, env.get_template, 'missing.html') + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(ByteCodeCacheTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/core_tags.py b/module/lib/jinja2/testsuite/core_tags.py new file mode 100644 index 000000000..f1a20fd44 --- /dev/null +++ b/module/lib/jinja2/testsuite/core_tags.py @@ -0,0 +1,305 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.core_tags + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Test the core tags like for and if. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Environment, TemplateSyntaxError, UndefinedError, \ + DictLoader + +env = Environment() + + +class ForLoopTestCase(JinjaTestCase): + + def test_simple(self): + tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}') + assert tmpl.render(seq=list(range(10))) == '0123456789' + + def test_else(self): + tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}') + assert tmpl.render() == '...' + + def test_empty_blocks(self): + tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>') + assert tmpl.render() == '<>' + + def test_context_vars(self): + tmpl = env.from_string('''{% for item in seq -%} + {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{ + loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{ + loop.length }}###{% endfor %}''') + one, two, _ = tmpl.render(seq=[0, 1]).split('###') + (one_index, one_index0, one_revindex, one_revindex0, one_first, + one_last, one_length) = one.split('|') + (two_index, two_index0, two_revindex, two_revindex0, two_first, + two_last, two_length) = two.split('|') + + assert int(one_index) == 1 and int(two_index) == 2 + assert int(one_index0) == 0 and int(two_index0) == 1 + assert int(one_revindex) == 2 and int(two_revindex) == 1 + assert int(one_revindex0) == 1 and int(two_revindex0) == 0 + assert one_first == 'True' and two_first == 'False' + assert one_last == 'False' and two_last == 'True' + assert one_length == two_length == '2' + + def test_cycling(self): + tmpl = env.from_string('''{% for item in seq %}{{ + loop.cycle('<1>', '<2>') }}{% endfor %}{% + for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''') + output = tmpl.render(seq=list(range(4)), through=('<1>', '<2>')) + assert output == '<1><2>' * 4 + + def test_scope(self): + tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}') + output = tmpl.render(seq=list(range(10))) + assert not output + + def test_varlen(self): + def inner(): + for item in range(5): + yield item + tmpl = env.from_string('{% for item in iter %}{{ item }}{% endfor %}') + output = tmpl.render(iter=inner()) + assert output == '01234' + + def test_noniter(self): + tmpl = env.from_string('{% for item in none %}...{% endfor %}') + self.assert_raises(TypeError, tmpl.render) + + def test_recursive(self): + tmpl = env.from_string('''{% for item in seq recursive -%} + [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}] + {%- endfor %}''') + assert tmpl.render(seq=[ + dict(a=1, b=[dict(a=1), dict(a=2)]), + dict(a=2, b=[dict(a=1), dict(a=2)]), + dict(a=3, b=[dict(a='a')]) + ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]' + + def test_recursive_depth0(self): + tmpl = env.from_string('''{% for item in seq recursive -%} + [{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}] + {%- endfor %}''') + self.assertEqual(tmpl.render(seq=[ + dict(a=1, b=[dict(a=1), dict(a=2)]), + dict(a=2, b=[dict(a=1), dict(a=2)]), + dict(a=3, b=[dict(a='a')]) + ]), '[0:1<[1:1][1:2]>][0:2<[1:1][1:2]>][0:3<[1:a]>]') + + def test_recursive_depth(self): + tmpl = env.from_string('''{% for item in seq recursive -%} + [{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}] + {%- endfor %}''') + self.assertEqual(tmpl.render(seq=[ + dict(a=1, b=[dict(a=1), dict(a=2)]), + dict(a=2, b=[dict(a=1), dict(a=2)]), + dict(a=3, b=[dict(a='a')]) + ]), '[1:1<[2:1][2:2]>][1:2<[2:1][2:2]>][1:3<[2:a]>]') + + def test_looploop(self): + tmpl = env.from_string('''{% for row in table %} + {%- set rowloop = loop -%} + {% for cell in row -%} + [{{ rowloop.index }}|{{ loop.index }}] + {%- endfor %} + {%- endfor %}''') + assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]' + + def test_reversed_bug(self): + tmpl = env.from_string('{% for i in items %}{{ i }}' + '{% if not loop.last %}' + ',{% endif %}{% endfor %}') + assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3' + + def test_loop_errors(self): + tmpl = env.from_string('''{% for item in [1] if loop.index + == 0 %}...{% endfor %}''') + self.assert_raises(UndefinedError, tmpl.render) + tmpl = env.from_string('''{% for item in [] %}...{% else + %}{{ loop }}{% endfor %}''') + assert tmpl.render() == '' + + def test_loop_filter(self): + tmpl = env.from_string('{% for item in range(10) if item ' + 'is even %}[{{ item }}]{% endfor %}') + assert tmpl.render() == '[0][2][4][6][8]' + tmpl = env.from_string(''' + {%- for item in range(10) if item is even %}[{{ + loop.index }}:{{ item }}]{% endfor %}''') + assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]' + + def test_loop_unassignable(self): + self.assert_raises(TemplateSyntaxError, env.from_string, + '{% for loop in seq %}...{% endfor %}') + + def test_scoped_special_var(self): + t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}' + '|{{ loop.first }}{% endfor %}]{% endfor %}') + assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]' + + def test_scoped_loop_var(self): + t = env.from_string('{% for x in seq %}{{ loop.first }}' + '{% for y in seq %}{% endfor %}{% endfor %}') + assert t.render(seq='ab') == 'TrueFalse' + t = env.from_string('{% for x in seq %}{% for y in seq %}' + '{{ loop.first }}{% endfor %}{% endfor %}') + assert t.render(seq='ab') == 'TrueFalseTrueFalse' + + def test_recursive_empty_loop_iter(self): + t = env.from_string(''' + {%- for item in foo recursive -%}{%- endfor -%} + ''') + assert t.render(dict(foo=[])) == '' + + def test_call_in_loop(self): + t = env.from_string(''' + {%- macro do_something() -%} + [{{ caller() }}] + {%- endmacro %} + + {%- for i in [1, 2, 3] %} + {%- call do_something() -%} + {{ i }} + {%- endcall %} + {%- endfor -%} + ''') + assert t.render() == '[1][2][3]' + + def test_scoping_bug(self): + t = env.from_string(''' + {%- for item in foo %}...{{ item }}...{% endfor %} + {%- macro item(a) %}...{{ a }}...{% endmacro %} + {{- item(2) -}} + ''') + assert t.render(foo=(1,)) == '...1......2...' + + def test_unpacking(self): + tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}' + '{{ a }}|{{ b }}|{{ c }}{% endfor %}') + assert tmpl.render() == '1|2|3' + + +class IfConditionTestCase(JinjaTestCase): + + def test_simple(self): + tmpl = env.from_string('''{% if true %}...{% endif %}''') + assert tmpl.render() == '...' + + def test_elif(self): + tmpl = env.from_string('''{% if false %}XXX{% elif true + %}...{% else %}XXX{% endif %}''') + assert tmpl.render() == '...' + + def test_else(self): + tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}') + assert tmpl.render() == '...' + + def test_empty(self): + tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]') + assert tmpl.render() == '[]' + + def test_complete(self): + tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}' + 'C{% else %}D{% endif %}') + assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C' + + def test_no_scope(self): + tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}') + assert tmpl.render(a=True) == '1' + tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}') + assert tmpl.render() == '1' + + +class MacrosTestCase(JinjaTestCase): + env = Environment(trim_blocks=True) + + def test_simple(self): + tmpl = self.env.from_string('''\ +{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %} +{{ say_hello('Peter') }}''') + assert tmpl.render() == 'Hello Peter!' + + def test_scoping(self): + tmpl = self.env.from_string('''\ +{% macro level1(data1) %} +{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %} +{{ level2('bar') }}{% endmacro %} +{{ level1('foo') }}''') + assert tmpl.render() == 'foo|bar' + + def test_arguments(self): + tmpl = self.env.from_string('''\ +{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %} +{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''') + assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d' + + def test_varargs(self): + tmpl = self.env.from_string('''\ +{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\ +{{ test(1, 2, 3) }}''') + assert tmpl.render() == '1|2|3' + + def test_simple_call(self): + tmpl = self.env.from_string('''\ +{% macro test() %}[[{{ caller() }}]]{% endmacro %}\ +{% call test() %}data{% endcall %}''') + assert tmpl.render() == '[[data]]' + + def test_complex_call(self): + tmpl = self.env.from_string('''\ +{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\ +{% call(data) test() %}{{ data }}{% endcall %}''') + assert tmpl.render() == '[[data]]' + + def test_caller_undefined(self): + tmpl = self.env.from_string('''\ +{% set caller = 42 %}\ +{% macro test() %}{{ caller is not defined }}{% endmacro %}\ +{{ test() }}''') + assert tmpl.render() == 'True' + + def test_include(self): + self.env = Environment(loader=DictLoader({'include': + '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'})) + tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}') + assert tmpl.render() == '[foo]' + + def test_macro_api(self): + tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}' + '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}' + '{% macro baz() %}{{ caller() }}{% endmacro %}') + assert tmpl.module.foo.arguments == ('a', 'b') + assert tmpl.module.foo.defaults == () + assert tmpl.module.foo.name == 'foo' + assert not tmpl.module.foo.caller + assert not tmpl.module.foo.catch_kwargs + assert not tmpl.module.foo.catch_varargs + assert tmpl.module.bar.arguments == () + assert tmpl.module.bar.defaults == () + assert not tmpl.module.bar.caller + assert tmpl.module.bar.catch_kwargs + assert tmpl.module.bar.catch_varargs + assert tmpl.module.baz.caller + + def test_callself(self): + tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|' + '{{ foo(x - 1) }}{% endif %}{% endmacro %}' + '{{ foo(5) }}') + assert tmpl.render() == '5|4|3|2|1' + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(ForLoopTestCase)) + suite.addTest(unittest.makeSuite(IfConditionTestCase)) + suite.addTest(unittest.makeSuite(MacrosTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/debug.py b/module/lib/jinja2/testsuite/debug.py new file mode 100644 index 000000000..2588a83ea --- /dev/null +++ b/module/lib/jinja2/testsuite/debug.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.debug + ~~~~~~~~~~~~~~~~~~~~~~ + + Tests the debug system. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase, filesystem_loader + +from jinja2 import Environment, TemplateSyntaxError + +env = Environment(loader=filesystem_loader) + + +class DebugTestCase(JinjaTestCase): + + def test_runtime_error(self): + def test(): + tmpl.render(fail=lambda: 1 / 0) + tmpl = env.get_template('broken.html') + self.assert_traceback_matches(test, r''' + File ".*?broken.html", line 2, in (top-level template code|<module>) + \{\{ fail\(\) \}\} + File ".*?debug.pyc?", line \d+, in <lambda> + tmpl\.render\(fail=lambda: 1 / 0\) +ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero +''') + + def test_syntax_error(self): + # XXX: the .*? is necessary for python3 which does not hide + # some of the stack frames we don't want to show. Not sure + # what's up with that, but that is not that critical. Should + # be fixed though. + self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm) + File ".*?syntaxerror.html", line 4, in (template|<module>) + \{% endif %\}.*? +(jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'. + ''') + + def test_regular_syntax_error(self): + def test(): + raise TemplateSyntaxError('wtf', 42) + self.assert_traceback_matches(test, r''' + File ".*debug.pyc?", line \d+, in test + raise TemplateSyntaxError\('wtf', 42\) +(jinja2\.exceptions\.)?TemplateSyntaxError: wtf + line 42''') + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(DebugTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/doctests.py b/module/lib/jinja2/testsuite/doctests.py new file mode 100644 index 000000000..616d3b6ee --- /dev/null +++ b/module/lib/jinja2/testsuite/doctests.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.doctests + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + The doctests. Collects all tests we want to test from + the Jinja modules. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest +import doctest + + +def suite(): + from jinja2 import utils, sandbox, runtime, meta, loaders, \ + ext, environment, bccache, nodes + suite = unittest.TestSuite() + suite.addTest(doctest.DocTestSuite(utils)) + suite.addTest(doctest.DocTestSuite(sandbox)) + suite.addTest(doctest.DocTestSuite(runtime)) + suite.addTest(doctest.DocTestSuite(meta)) + suite.addTest(doctest.DocTestSuite(loaders)) + suite.addTest(doctest.DocTestSuite(ext)) + suite.addTest(doctest.DocTestSuite(environment)) + suite.addTest(doctest.DocTestSuite(bccache)) + suite.addTest(doctest.DocTestSuite(nodes)) + return suite diff --git a/module/lib/jinja2/testsuite/ext.py b/module/lib/jinja2/testsuite/ext.py new file mode 100644 index 000000000..0f93be945 --- /dev/null +++ b/module/lib/jinja2/testsuite/ext.py @@ -0,0 +1,459 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.ext + ~~~~~~~~~~~~~~~~~~~~ + + Tests for the extensions. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import re +import unittest + +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Environment, DictLoader, contextfunction, nodes +from jinja2.exceptions import TemplateAssertionError +from jinja2.ext import Extension +from jinja2.lexer import Token, count_newlines +from jinja2._compat import next, BytesIO, itervalues, text_type + +importable_object = 23 + +_gettext_re = re.compile(r'_\((.*?)\)(?s)') + + +i18n_templates = { + 'master.html': '<title>{{ page_title|default(_("missing")) }}</title>' + '{% block body %}{% endblock %}', + 'child.html': '{% extends "master.html" %}{% block body %}' + '{% trans %}watch out{% endtrans %}{% endblock %}', + 'plural.html': '{% trans user_count %}One user online{% pluralize %}' + '{{ user_count }} users online{% endtrans %}', + 'plural2.html': '{% trans user_count=get_user_count() %}{{ user_count }}s' + '{% pluralize %}{{ user_count }}p{% endtrans %}', + 'stringformat.html': '{{ _("User: %(num)s")|format(num=user_count) }}' +} + +newstyle_i18n_templates = { + 'master.html': '<title>{{ page_title|default(_("missing")) }}</title>' + '{% block body %}{% endblock %}', + 'child.html': '{% extends "master.html" %}{% block body %}' + '{% trans %}watch out{% endtrans %}{% endblock %}', + 'plural.html': '{% trans user_count %}One user online{% pluralize %}' + '{{ user_count }} users online{% endtrans %}', + 'stringformat.html': '{{ _("User: %(num)s", num=user_count) }}', + 'ngettext.html': '{{ ngettext("%(num)s apple", "%(num)s apples", apples) }}', + 'ngettext_long.html': '{% trans num=apples %}{{ num }} apple{% pluralize %}' + '{{ num }} apples{% endtrans %}', + 'transvars1.html': '{% trans %}User: {{ num }}{% endtrans %}', + 'transvars2.html': '{% trans num=count %}User: {{ num }}{% endtrans %}', + 'transvars3.html': '{% trans count=num %}User: {{ count }}{% endtrans %}', + 'novars.html': '{% trans %}%(hello)s{% endtrans %}', + 'vars.html': '{% trans %}{{ foo }}%(foo)s{% endtrans %}', + 'explicitvars.html': '{% trans foo="42" %}%(foo)s{% endtrans %}' +} + + +languages = { + 'de': { + 'missing': u'fehlend', + 'watch out': u'pass auf', + 'One user online': u'Ein Benutzer online', + '%(user_count)s users online': u'%(user_count)s Benutzer online', + 'User: %(num)s': u'Benutzer: %(num)s', + 'User: %(count)s': u'Benutzer: %(count)s', + '%(num)s apple': u'%(num)s Apfel', + '%(num)s apples': u'%(num)s Ãpfel' + } +} + + +@contextfunction +def gettext(context, string): + language = context.get('LANGUAGE', 'en') + return languages.get(language, {}).get(string, string) + + +@contextfunction +def ngettext(context, s, p, n): + language = context.get('LANGUAGE', 'en') + if n != 1: + return languages.get(language, {}).get(p, p) + return languages.get(language, {}).get(s, s) + + +i18n_env = Environment( + loader=DictLoader(i18n_templates), + extensions=['jinja2.ext.i18n'] +) +i18n_env.globals.update({ + '_': gettext, + 'gettext': gettext, + 'ngettext': ngettext +}) + +newstyle_i18n_env = Environment( + loader=DictLoader(newstyle_i18n_templates), + extensions=['jinja2.ext.i18n'] +) +newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True) + +class TestExtension(Extension): + tags = set(['test']) + ext_attr = 42 + + def parse(self, parser): + return nodes.Output([self.call_method('_dump', [ + nodes.EnvironmentAttribute('sandboxed'), + self.attr('ext_attr'), + nodes.ImportedName(__name__ + '.importable_object'), + nodes.ContextReference() + ])]).set_lineno(next(parser.stream).lineno) + + def _dump(self, sandboxed, ext_attr, imported_object, context): + return '%s|%s|%s|%s' % ( + sandboxed, + ext_attr, + imported_object, + context.blocks + ) + + +class PreprocessorExtension(Extension): + + def preprocess(self, source, name, filename=None): + return source.replace('[[TEST]]', '({{ foo }})') + + +class StreamFilterExtension(Extension): + + def filter_stream(self, stream): + for token in stream: + if token.type == 'data': + for t in self.interpolate(token): + yield t + else: + yield token + + def interpolate(self, token): + pos = 0 + end = len(token.value) + lineno = token.lineno + while 1: + match = _gettext_re.search(token.value, pos) + if match is None: + break + value = token.value[pos:match.start()] + if value: + yield Token(lineno, 'data', value) + lineno += count_newlines(token.value) + yield Token(lineno, 'variable_begin', None) + yield Token(lineno, 'name', 'gettext') + yield Token(lineno, 'lparen', None) + yield Token(lineno, 'string', match.group(1)) + yield Token(lineno, 'rparen', None) + yield Token(lineno, 'variable_end', None) + pos = match.end() + if pos < end: + yield Token(lineno, 'data', token.value[pos:]) + + +class ExtensionsTestCase(JinjaTestCase): + + def test_extend_late(self): + env = Environment() + env.add_extension('jinja2.ext.autoescape') + t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}') + assert t.render() == '<test>' + + def test_loop_controls(self): + env = Environment(extensions=['jinja2.ext.loopcontrols']) + + tmpl = env.from_string(''' + {%- for item in [1, 2, 3, 4] %} + {%- if item % 2 == 0 %}{% continue %}{% endif -%} + {{ item }} + {%- endfor %}''') + assert tmpl.render() == '13' + + tmpl = env.from_string(''' + {%- for item in [1, 2, 3, 4] %} + {%- if item > 2 %}{% break %}{% endif -%} + {{ item }} + {%- endfor %}''') + assert tmpl.render() == '12' + + def test_do(self): + env = Environment(extensions=['jinja2.ext.do']) + tmpl = env.from_string(''' + {%- set items = [] %} + {%- for char in "foo" %} + {%- do items.append(loop.index0 ~ char) %} + {%- endfor %}{{ items|join(', ') }}''') + assert tmpl.render() == '0f, 1o, 2o' + + def test_with(self): + env = Environment(extensions=['jinja2.ext.with_']) + tmpl = env.from_string('''\ + {% with a=42, b=23 -%} + {{ a }} = {{ b }} + {% endwith -%} + {{ a }} = {{ b }}\ + ''') + assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \ + == ['42 = 23', '1 = 2'] + + def test_extension_nodes(self): + env = Environment(extensions=[TestExtension]) + tmpl = env.from_string('{% test %}') + assert tmpl.render() == 'False|42|23|{}' + + def test_identifier(self): + assert TestExtension.identifier == __name__ + '.TestExtension' + + def test_rebinding(self): + original = Environment(extensions=[TestExtension]) + overlay = original.overlay() + for env in original, overlay: + for ext in itervalues(env.extensions): + assert ext.environment is env + + def test_preprocessor_extension(self): + env = Environment(extensions=[PreprocessorExtension]) + tmpl = env.from_string('{[[TEST]]}') + assert tmpl.render(foo=42) == '{(42)}' + + def test_streamfilter_extension(self): + env = Environment(extensions=[StreamFilterExtension]) + env.globals['gettext'] = lambda x: x.upper() + tmpl = env.from_string('Foo _(bar) Baz') + out = tmpl.render() + assert out == 'Foo BAR Baz' + + def test_extension_ordering(self): + class T1(Extension): + priority = 1 + class T2(Extension): + priority = 2 + env = Environment(extensions=[T1, T2]) + ext = list(env.iter_extensions()) + assert ext[0].__class__ is T1 + assert ext[1].__class__ is T2 + + +class InternationalizationTestCase(JinjaTestCase): + + def test_trans(self): + tmpl = i18n_env.get_template('child.html') + assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf' + + def test_trans_plural(self): + tmpl = i18n_env.get_template('plural.html') + assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online' + assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online' + + def test_trans_plural_with_functions(self): + tmpl = i18n_env.get_template('plural2.html') + def get_user_count(): + get_user_count.called += 1 + return 1 + get_user_count.called = 0 + assert tmpl.render(LANGUAGE='de', get_user_count=get_user_count) == '1s' + assert get_user_count.called == 1 + + def test_complex_plural(self): + tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% ' + 'pluralize count %}{{ count }} items{% endtrans %}') + assert tmpl.render() == '2 items' + self.assert_raises(TemplateAssertionError, i18n_env.from_string, + '{% trans foo %}...{% pluralize bar %}...{% endtrans %}') + + def test_trans_stringformatting(self): + tmpl = i18n_env.get_template('stringformat.html') + assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5' + + def test_extract(self): + from jinja2.ext import babel_extract + source = BytesIO(''' + {{ gettext('Hello World') }} + {% trans %}Hello World{% endtrans %} + {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %} + '''.encode('ascii')) # make python 3 happy + assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [ + (2, 'gettext', u'Hello World', []), + (3, 'gettext', u'Hello World', []), + (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), []) + ] + + def test_comment_extract(self): + from jinja2.ext import babel_extract + source = BytesIO(''' + {# trans first #} + {{ gettext('Hello World') }} + {% trans %}Hello World{% endtrans %}{# trans second #} + {#: third #} + {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %} + '''.encode('utf-8')) # make python 3 happy + assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [ + (3, 'gettext', u'Hello World', ['first']), + (4, 'gettext', u'Hello World', ['second']), + (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third']) + ] + + +class NewstyleInternationalizationTestCase(JinjaTestCase): + + def test_trans(self): + tmpl = newstyle_i18n_env.get_template('child.html') + assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf' + + def test_trans_plural(self): + tmpl = newstyle_i18n_env.get_template('plural.html') + assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online' + assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online' + + def test_complex_plural(self): + tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% ' + 'pluralize count %}{{ count }} items{% endtrans %}') + assert tmpl.render() == '2 items' + self.assert_raises(TemplateAssertionError, i18n_env.from_string, + '{% trans foo %}...{% pluralize bar %}...{% endtrans %}') + + def test_trans_stringformatting(self): + tmpl = newstyle_i18n_env.get_template('stringformat.html') + assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5' + + def test_newstyle_plural(self): + tmpl = newstyle_i18n_env.get_template('ngettext.html') + assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel' + assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Ãpfel' + + def test_autoescape_support(self): + env = Environment(extensions=['jinja2.ext.autoescape', + 'jinja2.ext.i18n']) + env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>', + lambda s, p, n: s, newstyle=True) + t = env.from_string('{% autoescape ae %}{{ gettext("foo", name=' + '"<test>") }}{% endautoescape %}') + assert t.render(ae=True) == '<strong>Wert: <test></strong>' + assert t.render(ae=False) == '<strong>Wert: <test></strong>' + + def test_num_used_twice(self): + tmpl = newstyle_i18n_env.get_template('ngettext_long.html') + assert tmpl.render(apples=5, LANGUAGE='de') == u'5 Ãpfel' + + def test_num_called_num(self): + source = newstyle_i18n_env.compile(''' + {% trans num=3 %}{{ num }} apple{% pluralize + %}{{ num }} apples{% endtrans %} + ''', raw=True) + # quite hacky, but the only way to properly test that. The idea is + # that the generated code does not pass num twice (although that + # would work) for better performance. This only works on the + # newstyle gettext of course + assert re.search(r"l_ngettext, u?'\%\(num\)s apple', u?'\%\(num\)s " + r"apples', 3", source) is not None + + def test_trans_vars(self): + t1 = newstyle_i18n_env.get_template('transvars1.html') + t2 = newstyle_i18n_env.get_template('transvars2.html') + t3 = newstyle_i18n_env.get_template('transvars3.html') + assert t1.render(num=1, LANGUAGE='de') == 'Benutzer: 1' + assert t2.render(count=23, LANGUAGE='de') == 'Benutzer: 23' + assert t3.render(num=42, LANGUAGE='de') == 'Benutzer: 42' + + def test_novars_vars_escaping(self): + t = newstyle_i18n_env.get_template('novars.html') + assert t.render() == '%(hello)s' + t = newstyle_i18n_env.get_template('vars.html') + assert t.render(foo='42') == '42%(foo)s' + t = newstyle_i18n_env.get_template('explicitvars.html') + assert t.render() == '%(foo)s' + + +class AutoEscapeTestCase(JinjaTestCase): + + def test_scoped_setting(self): + env = Environment(extensions=['jinja2.ext.autoescape'], + autoescape=True) + tmpl = env.from_string(''' + {{ "<HelloWorld>" }} + {% autoescape false %} + {{ "<HelloWorld>" }} + {% endautoescape %} + {{ "<HelloWorld>" }} + ''') + assert tmpl.render().split() == \ + [u'<HelloWorld>', u'<HelloWorld>', u'<HelloWorld>'] + + env = Environment(extensions=['jinja2.ext.autoescape'], + autoescape=False) + tmpl = env.from_string(''' + {{ "<HelloWorld>" }} + {% autoescape true %} + {{ "<HelloWorld>" }} + {% endautoescape %} + {{ "<HelloWorld>" }} + ''') + assert tmpl.render().split() == \ + [u'<HelloWorld>', u'<HelloWorld>', u'<HelloWorld>'] + + def test_nonvolatile(self): + env = Environment(extensions=['jinja2.ext.autoescape'], + autoescape=True) + tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}') + assert tmpl.render() == ' foo="<test>"' + tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}' + '|xmlattr|escape }}{% endautoescape %}') + assert tmpl.render() == ' foo="&lt;test&gt;"' + + def test_volatile(self): + env = Environment(extensions=['jinja2.ext.autoescape'], + autoescape=True) + tmpl = env.from_string('{% autoescape foo %}{{ {"foo": "<test>"}' + '|xmlattr|escape }}{% endautoescape %}') + assert tmpl.render(foo=False) == ' foo="&lt;test&gt;"' + assert tmpl.render(foo=True) == ' foo="<test>"' + + def test_scoping(self): + env = Environment(extensions=['jinja2.ext.autoescape']) + tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}' + '{% endautoescape %}{{ x }}{{ "<y>" }}') + assert tmpl.render(x=1) == '<x>1<y>' + + def test_volatile_scoping(self): + env = Environment(extensions=['jinja2.ext.autoescape']) + tmplsource = ''' + {% autoescape val %} + {% macro foo(x) %} + [{{ x }}] + {% endmacro %} + {{ foo().__class__.__name__ }} + {% endautoescape %} + {{ '<testing>' }} + ''' + tmpl = env.from_string(tmplsource) + assert tmpl.render(val=True).split()[0] == 'Markup' + assert tmpl.render(val=False).split()[0] == text_type.__name__ + + # looking at the source we should see <testing> there in raw + # (and then escaped as well) + env = Environment(extensions=['jinja2.ext.autoescape']) + pysource = env.compile(tmplsource, raw=True) + assert '<testing>\\n' in pysource + + env = Environment(extensions=['jinja2.ext.autoescape'], + autoescape=True) + pysource = env.compile(tmplsource, raw=True) + assert '<testing>\\n' in pysource + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(ExtensionsTestCase)) + suite.addTest(unittest.makeSuite(InternationalizationTestCase)) + suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase)) + suite.addTest(unittest.makeSuite(AutoEscapeTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/filters.py b/module/lib/jinja2/testsuite/filters.py new file mode 100644 index 000000000..282dd2d85 --- /dev/null +++ b/module/lib/jinja2/testsuite/filters.py @@ -0,0 +1,515 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.filters + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Tests for the jinja filters. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Markup, Environment +from jinja2._compat import text_type, implements_to_string + +env = Environment() + + +class FilterTestCase(JinjaTestCase): + + def test_filter_calling(self): + rv = env.call_filter('sum', [1, 2, 3]) + self.assert_equal(rv, 6) + + def test_capitalize(self): + tmpl = env.from_string('{{ "foo bar"|capitalize }}') + assert tmpl.render() == 'Foo bar' + + def test_center(self): + tmpl = env.from_string('{{ "foo"|center(9) }}') + assert tmpl.render() == ' foo ' + + def test_default(self): + tmpl = env.from_string( + "{{ missing|default('no') }}|{{ false|default('no') }}|" + "{{ false|default('no', true) }}|{{ given|default('no') }}" + ) + assert tmpl.render(given='yes') == 'no|False|no|yes' + + def test_dictsort(self): + tmpl = env.from_string( + '{{ foo|dictsort }}|' + '{{ foo|dictsort(true) }}|' + '{{ foo|dictsort(false, "value") }}' + ) + out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3}) + assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|" + "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|" + "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]") + + def test_batch(self): + tmpl = env.from_string("{{ foo|batch(3)|list }}|" + "{{ foo|batch(3, 'X')|list }}") + out = tmpl.render(foo=list(range(10))) + assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|" + "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]") + + def test_slice(self): + tmpl = env.from_string('{{ foo|slice(3)|list }}|' + '{{ foo|slice(3, "X")|list }}') + out = tmpl.render(foo=list(range(10))) + assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|" + "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]") + + def test_escape(self): + tmpl = env.from_string('''{{ '<">&'|escape }}''') + out = tmpl.render() + assert out == '<">&' + + def test_striptags(self): + tmpl = env.from_string('''{{ foo|striptags }}''') + out = tmpl.render(foo=' <p>just a small \n <a href="#">' + 'example</a> link</p>\n<p>to a webpage</p> ' + '<!-- <p>and some commented stuff</p> -->') + assert out == 'just a small example link to a webpage' + + def test_filesizeformat(self): + tmpl = env.from_string( + '{{ 100|filesizeformat }}|' + '{{ 1000|filesizeformat }}|' + '{{ 1000000|filesizeformat }}|' + '{{ 1000000000|filesizeformat }}|' + '{{ 1000000000000|filesizeformat }}|' + '{{ 100|filesizeformat(true) }}|' + '{{ 1000|filesizeformat(true) }}|' + '{{ 1000000|filesizeformat(true) }}|' + '{{ 1000000000|filesizeformat(true) }}|' + '{{ 1000000000000|filesizeformat(true) }}' + ) + out = tmpl.render() + self.assert_equal(out, ( + '100 Bytes|1.0 kB|1.0 MB|1.0 GB|1.0 TB|100 Bytes|' + '1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB' + )) + + def test_filesizeformat_issue59(self): + tmpl = env.from_string( + '{{ 300|filesizeformat }}|' + '{{ 3000|filesizeformat }}|' + '{{ 3000000|filesizeformat }}|' + '{{ 3000000000|filesizeformat }}|' + '{{ 3000000000000|filesizeformat }}|' + '{{ 300|filesizeformat(true) }}|' + '{{ 3000|filesizeformat(true) }}|' + '{{ 3000000|filesizeformat(true) }}' + ) + out = tmpl.render() + self.assert_equal(out, ( + '300 Bytes|3.0 kB|3.0 MB|3.0 GB|3.0 TB|300 Bytes|' + '2.9 KiB|2.9 MiB' + )) + + + def test_first(self): + tmpl = env.from_string('{{ foo|first }}') + out = tmpl.render(foo=list(range(10))) + assert out == '0' + + def test_float(self): + tmpl = env.from_string('{{ "42"|float }}|' + '{{ "ajsghasjgd"|float }}|' + '{{ "32.32"|float }}') + out = tmpl.render() + assert out == '42.0|0.0|32.32' + + def test_format(self): + tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''') + out = tmpl.render() + assert out == 'a|b' + + def test_indent(self): + tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}') + text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2) + out = tmpl.render(foo=text) + assert out == ('foo bar foo bar\n foo bar foo bar| ' + 'foo bar foo bar\n foo bar foo bar') + + def test_int(self): + tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|' + '{{ "32.32"|int }}') + out = tmpl.render() + assert out == '42|0|32' + + def test_join(self): + tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}') + out = tmpl.render() + assert out == '1|2|3' + + env2 = Environment(autoescape=True) + tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}') + assert tmpl.render() == '<foo><span>foo</span>' + + def test_join_attribute(self): + class User(object): + def __init__(self, username): + self.username = username + tmpl = env.from_string('''{{ users|join(', ', 'username') }}''') + assert tmpl.render(users=map(User, ['foo', 'bar'])) == 'foo, bar' + + def test_last(self): + tmpl = env.from_string('''{{ foo|last }}''') + out = tmpl.render(foo=list(range(10))) + assert out == '9' + + def test_length(self): + tmpl = env.from_string('''{{ "hello world"|length }}''') + out = tmpl.render() + assert out == '11' + + def test_lower(self): + tmpl = env.from_string('''{{ "FOO"|lower }}''') + out = tmpl.render() + assert out == 'foo' + + def test_pprint(self): + from pprint import pformat + tmpl = env.from_string('''{{ data|pprint }}''') + data = list(range(1000)) + assert tmpl.render(data=data) == pformat(data) + + def test_random(self): + tmpl = env.from_string('''{{ seq|random }}''') + seq = list(range(100)) + for _ in range(10): + assert int(tmpl.render(seq=seq)) in seq + + def test_reverse(self): + tmpl = env.from_string('{{ "foobar"|reverse|join }}|' + '{{ [1, 2, 3]|reverse|list }}') + assert tmpl.render() == 'raboof|[3, 2, 1]' + + def test_string(self): + x = [1, 2, 3, 4, 5] + tmpl = env.from_string('''{{ obj|string }}''') + assert tmpl.render(obj=x) == text_type(x) + + def test_title(self): + tmpl = env.from_string('''{{ "foo bar"|title }}''') + assert tmpl.render() == "Foo Bar" + tmpl = env.from_string('''{{ "foo's bar"|title }}''') + assert tmpl.render() == "Foo's Bar" + tmpl = env.from_string('''{{ "foo bar"|title }}''') + assert tmpl.render() == "Foo Bar" + tmpl = env.from_string('''{{ "f bar f"|title }}''') + assert tmpl.render() == "F Bar F" + tmpl = env.from_string('''{{ "foo-bar"|title }}''') + assert tmpl.render() == "Foo-Bar" + tmpl = env.from_string('''{{ "foo\tbar"|title }}''') + assert tmpl.render() == "Foo\tBar" + tmpl = env.from_string('''{{ "FOO\tBAR"|title }}''') + assert tmpl.render() == "Foo\tBar" + + def test_truncate(self): + tmpl = env.from_string( + '{{ data|truncate(15, true, ">>>") }}|' + '{{ data|truncate(15, false, ">>>") }}|' + '{{ smalldata|truncate(15) }}' + ) + out = tmpl.render(data='foobar baz bar' * 1000, + smalldata='foobar baz bar') + assert out == 'foobar baz barf>>>|foobar baz >>>|foobar baz bar' + + def test_upper(self): + tmpl = env.from_string('{{ "foo"|upper }}') + assert tmpl.render() == 'FOO' + + def test_urlize(self): + tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}') + assert tmpl.render() == 'foo <a href="http://www.example.com/">'\ + 'http://www.example.com/</a> bar' + + def test_wordcount(self): + tmpl = env.from_string('{{ "foo bar baz"|wordcount }}') + assert tmpl.render() == '3' + + def test_block(self): + tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}') + assert tmpl.render() == '<hehe>' + + def test_chaining(self): + tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''') + assert tmpl.render() == '<FOO>' + + def test_sum(self): + tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''') + assert tmpl.render() == '21' + + def test_sum_attributes(self): + tmpl = env.from_string('''{{ values|sum('value') }}''') + assert tmpl.render(values=[ + {'value': 23}, + {'value': 1}, + {'value': 18}, + ]) == '42' + + def test_sum_attributes_nested(self): + tmpl = env.from_string('''{{ values|sum('real.value') }}''') + assert tmpl.render(values=[ + {'real': {'value': 23}}, + {'real': {'value': 1}}, + {'real': {'value': 18}}, + ]) == '42' + + def test_sum_attributes_tuple(self): + tmpl = env.from_string('''{{ values.items()|sum('1') }}''') + assert tmpl.render(values={ + 'foo': 23, + 'bar': 1, + 'baz': 18, + }) == '42' + + def test_abs(self): + tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''') + assert tmpl.render() == '1|1', tmpl.render() + + def test_round_positive(self): + tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|' + "{{ 2.1234|round(3, 'floor') }}|" + "{{ 2.1|round(0, 'ceil') }}") + assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render() + + def test_round_negative(self): + tmpl = env.from_string('{{ 21.3|round(-1)}}|' + "{{ 21.3|round(-1, 'ceil')}}|" + "{{ 21.3|round(-1, 'floor')}}") + assert tmpl.render() == '20.0|30.0|20.0',tmpl.render() + + def test_xmlattr(self): + tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, " + "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}") + out = tmpl.render().split() + assert len(out) == 3 + assert 'foo="42"' in out + assert 'bar="23"' in out + assert 'blub:blub="<?>"' in out + + def test_sort1(self): + tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}') + assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]' + + def test_sort2(self): + tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort) }}') + assert tmpl.render() == 'AbcD' + + def test_sort3(self): + tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''') + assert tmpl.render() == "['Bar', 'blah', 'foo']" + + def test_sort4(self): + @implements_to_string + class Magic(object): + def __init__(self, value): + self.value = value + def __str__(self): + return text_type(self.value) + tmpl = env.from_string('''{{ items|sort(attribute='value')|join }}''') + assert tmpl.render(items=map(Magic, [3, 2, 4, 1])) == '1234' + + def test_groupby(self): + tmpl = env.from_string(''' + {%- for grouper, list in [{'foo': 1, 'bar': 2}, + {'foo': 2, 'bar': 3}, + {'foo': 1, 'bar': 1}, + {'foo': 3, 'bar': 4}]|groupby('foo') -%} + {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}| + {%- endfor %}''') + assert tmpl.render().split('|') == [ + "1: 1, 2: 1, 1", + "2: 2, 3", + "3: 3, 4", + "" + ] + + def test_groupby_tuple_index(self): + tmpl = env.from_string(''' + {%- for grouper, list in [('a', 1), ('a', 2), ('b', 1)]|groupby(0) -%} + {{ grouper }}{% for x in list %}:{{ x.1 }}{% endfor %}| + {%- endfor %}''') + assert tmpl.render() == 'a:1:2|b:1|' + + def test_groupby_multidot(self): + class Date(object): + def __init__(self, day, month, year): + self.day = day + self.month = month + self.year = year + class Article(object): + def __init__(self, title, *date): + self.date = Date(*date) + self.title = title + articles = [ + Article('aha', 1, 1, 1970), + Article('interesting', 2, 1, 1970), + Article('really?', 3, 1, 1970), + Article('totally not', 1, 1, 1971) + ] + tmpl = env.from_string(''' + {%- for year, list in articles|groupby('date.year') -%} + {{ year }}{% for x in list %}[{{ x.title }}]{% endfor %}| + {%- endfor %}''') + assert tmpl.render(articles=articles).split('|') == [ + '1970[aha][interesting][really?]', + '1971[totally not]', + '' + ] + + def test_filtertag(self): + tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}" + "foobar{% endfilter %}") + assert tmpl.render() == 'fooBAR' + + def test_replace(self): + env = Environment() + tmpl = env.from_string('{{ string|replace("o", 42) }}') + assert tmpl.render(string='<foo>') == '<f4242>' + env = Environment(autoescape=True) + tmpl = env.from_string('{{ string|replace("o", 42) }}') + assert tmpl.render(string='<foo>') == '<f4242>' + tmpl = env.from_string('{{ string|replace("<", 42) }}') + assert tmpl.render(string='<foo>') == '42foo>' + tmpl = env.from_string('{{ string|replace("o", ">x<") }}') + assert tmpl.render(string=Markup('foo')) == 'f>x<>x<' + + def test_forceescape(self): + tmpl = env.from_string('{{ x|forceescape }}') + assert tmpl.render(x=Markup('<div />')) == u'<div />' + + def test_safe(self): + env = Environment(autoescape=True) + tmpl = env.from_string('{{ "<div>foo</div>"|safe }}') + assert tmpl.render() == '<div>foo</div>' + tmpl = env.from_string('{{ "<div>foo</div>" }}') + assert tmpl.render() == '<div>foo</div>' + + def test_urlencode(self): + env = Environment(autoescape=True) + tmpl = env.from_string('{{ "Hello, world!"|urlencode }}') + assert tmpl.render() == 'Hello%2C%20world%21' + tmpl = env.from_string('{{ o|urlencode }}') + assert tmpl.render(o=u"Hello, world\u203d") == "Hello%2C%20world%E2%80%BD" + assert tmpl.render(o=(("f", 1),)) == "f=1" + assert tmpl.render(o=(('f', 1), ("z", 2))) == "f=1&z=2" + assert tmpl.render(o=((u"\u203d", 1),)) == "%E2%80%BD=1" + assert tmpl.render(o={u"\u203d": 1}) == "%E2%80%BD=1" + assert tmpl.render(o={0: 1}) == "0=1" + + def test_simple_map(self): + env = Environment() + tmpl = env.from_string('{{ ["1", "2", "3"]|map("int")|sum }}') + self.assertEqual(tmpl.render(), '6') + + def test_attribute_map(self): + class User(object): + def __init__(self, name): + self.name = name + env = Environment() + users = [ + User('john'), + User('jane'), + User('mike'), + ] + tmpl = env.from_string('{{ users|map(attribute="name")|join("|") }}') + self.assertEqual(tmpl.render(users=users), 'john|jane|mike') + + def test_empty_map(self): + env = Environment() + tmpl = env.from_string('{{ none|map("upper")|list }}') + self.assertEqual(tmpl.render(), '[]') + + def test_simple_select(self): + env = Environment() + tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|select("odd")|join("|") }}') + self.assertEqual(tmpl.render(), '1|3|5') + + def test_bool_select(self): + env = Environment() + tmpl = env.from_string('{{ [none, false, 0, 1, 2, 3, 4, 5]|select|join("|") }}') + self.assertEqual(tmpl.render(), '1|2|3|4|5') + + def test_simple_reject(self): + env = Environment() + tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|reject("odd")|join("|") }}') + self.assertEqual(tmpl.render(), '2|4') + + def test_bool_reject(self): + env = Environment() + tmpl = env.from_string('{{ [none, false, 0, 1, 2, 3, 4, 5]|reject|join("|") }}') + self.assertEqual(tmpl.render(), 'None|False|0') + + def test_simple_select_attr(self): + class User(object): + def __init__(self, name, is_active): + self.name = name + self.is_active = is_active + env = Environment() + users = [ + User('john', True), + User('jane', True), + User('mike', False), + ] + tmpl = env.from_string('{{ users|selectattr("is_active")|' + 'map(attribute="name")|join("|") }}') + self.assertEqual(tmpl.render(users=users), 'john|jane') + + def test_simple_reject_attr(self): + class User(object): + def __init__(self, name, is_active): + self.name = name + self.is_active = is_active + env = Environment() + users = [ + User('john', True), + User('jane', True), + User('mike', False), + ] + tmpl = env.from_string('{{ users|rejectattr("is_active")|' + 'map(attribute="name")|join("|") }}') + self.assertEqual(tmpl.render(users=users), 'mike') + + def test_func_select_attr(self): + class User(object): + def __init__(self, id, name): + self.id = id + self.name = name + env = Environment() + users = [ + User(1, 'john'), + User(2, 'jane'), + User(3, 'mike'), + ] + tmpl = env.from_string('{{ users|selectattr("id", "odd")|' + 'map(attribute="name")|join("|") }}') + self.assertEqual(tmpl.render(users=users), 'john|mike') + + def test_func_reject_attr(self): + class User(object): + def __init__(self, id, name): + self.id = id + self.name = name + env = Environment() + users = [ + User(1, 'john'), + User(2, 'jane'), + User(3, 'mike'), + ] + tmpl = env.from_string('{{ users|rejectattr("id", "odd")|' + 'map(attribute="name")|join("|") }}') + self.assertEqual(tmpl.render(users=users), 'jane') + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(FilterTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/imports.py b/module/lib/jinja2/testsuite/imports.py new file mode 100644 index 000000000..3db9008de --- /dev/null +++ b/module/lib/jinja2/testsuite/imports.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.imports + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Tests the import features (with includes). + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Environment, DictLoader +from jinja2.exceptions import TemplateNotFound, TemplatesNotFound + + +test_env = Environment(loader=DictLoader(dict( + module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}', + header='[{{ foo }}|{{ 23 }}]', + o_printer='({{ o }})' +))) +test_env.globals['bar'] = 23 + + +class ImportsTestCase(JinjaTestCase): + + def test_context_imports(self): + t = test_env.from_string('{% import "module" as m %}{{ m.test() }}') + assert t.render(foo=42) == '[|23]' + t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}') + assert t.render(foo=42) == '[|23]' + t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}') + assert t.render(foo=42) == '[42|23]' + t = test_env.from_string('{% from "module" import test %}{{ test() }}') + assert t.render(foo=42) == '[|23]' + t = test_env.from_string('{% from "module" import test without context %}{{ test() }}') + assert t.render(foo=42) == '[|23]' + t = test_env.from_string('{% from "module" import test with context %}{{ test() }}') + assert t.render(foo=42) == '[42|23]' + + def test_trailing_comma(self): + test_env.from_string('{% from "foo" import bar, baz with context %}') + test_env.from_string('{% from "foo" import bar, baz, with context %}') + test_env.from_string('{% from "foo" import bar, with context %}') + test_env.from_string('{% from "foo" import bar, with, context %}') + test_env.from_string('{% from "foo" import bar, with with context %}') + + def test_exports(self): + m = test_env.from_string(''' + {% macro toplevel() %}...{% endmacro %} + {% macro __private() %}...{% endmacro %} + {% set variable = 42 %} + {% for item in [1] %} + {% macro notthere() %}{% endmacro %} + {% endfor %} + ''').module + assert m.toplevel() == '...' + assert not hasattr(m, '__missing') + assert m.variable == 42 + assert not hasattr(m, 'notthere') + + +class IncludesTestCase(JinjaTestCase): + + def test_context_include(self): + t = test_env.from_string('{% include "header" %}') + assert t.render(foo=42) == '[42|23]' + t = test_env.from_string('{% include "header" with context %}') + assert t.render(foo=42) == '[42|23]' + t = test_env.from_string('{% include "header" without context %}') + assert t.render(foo=42) == '[|23]' + + def test_choice_includes(self): + t = test_env.from_string('{% include ["missing", "header"] %}') + assert t.render(foo=42) == '[42|23]' + + t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}') + assert t.render(foo=42) == '' + + t = test_env.from_string('{% include ["missing", "missing2"] %}') + self.assert_raises(TemplateNotFound, t.render) + try: + t.render() + except TemplatesNotFound as e: + assert e.templates == ['missing', 'missing2'] + assert e.name == 'missing2' + else: + assert False, 'thou shalt raise' + + def test_includes(t, **ctx): + ctx['foo'] = 42 + assert t.render(ctx) == '[42|23]' + + t = test_env.from_string('{% include ["missing", "header"] %}') + test_includes(t) + t = test_env.from_string('{% include x %}') + test_includes(t, x=['missing', 'header']) + t = test_env.from_string('{% include [x, "header"] %}') + test_includes(t, x='missing') + t = test_env.from_string('{% include x %}') + test_includes(t, x='header') + t = test_env.from_string('{% include x %}') + test_includes(t, x='header') + t = test_env.from_string('{% include [x] %}') + test_includes(t, x='header') + + def test_include_ignoring_missing(self): + t = test_env.from_string('{% include "missing" %}') + self.assert_raises(TemplateNotFound, t.render) + for extra in '', 'with context', 'without context': + t = test_env.from_string('{% include "missing" ignore missing ' + + extra + ' %}') + assert t.render() == '' + + def test_context_include_with_overrides(self): + env = Environment(loader=DictLoader(dict( + main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}", + item="{{ item }}" + ))) + assert env.get_template("main").render() == "123" + + def test_unoptimized_scopes(self): + t = test_env.from_string(""" + {% macro outer(o) %} + {% macro inner() %} + {% include "o_printer" %} + {% endmacro %} + {{ inner() }} + {% endmacro %} + {{ outer("FOO") }} + """) + assert t.render().strip() == '(FOO)' + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(ImportsTestCase)) + suite.addTest(unittest.makeSuite(IncludesTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/inheritance.py b/module/lib/jinja2/testsuite/inheritance.py new file mode 100644 index 000000000..e0f51cda9 --- /dev/null +++ b/module/lib/jinja2/testsuite/inheritance.py @@ -0,0 +1,250 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.inheritance + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Tests the template inheritance feature. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Environment, DictLoader, TemplateError + + +LAYOUTTEMPLATE = '''\ +|{% block block1 %}block 1 from layout{% endblock %} +|{% block block2 %}block 2 from layout{% endblock %} +|{% block block3 %} +{% block block4 %}nested block 4 from layout{% endblock %} +{% endblock %}|''' + +LEVEL1TEMPLATE = '''\ +{% extends "layout" %} +{% block block1 %}block 1 from level1{% endblock %}''' + +LEVEL2TEMPLATE = '''\ +{% extends "level1" %} +{% block block2 %}{% block block5 %}nested block 5 from level2{% +endblock %}{% endblock %}''' + +LEVEL3TEMPLATE = '''\ +{% extends "level2" %} +{% block block5 %}block 5 from level3{% endblock %} +{% block block4 %}block 4 from level3{% endblock %} +''' + +LEVEL4TEMPLATE = '''\ +{% extends "level3" %} +{% block block3 %}block 3 from level4{% endblock %} +''' + +WORKINGTEMPLATE = '''\ +{% extends "layout" %} +{% block block1 %} + {% if false %} + {% block block2 %} + this should workd + {% endblock %} + {% endif %} +{% endblock %} +''' + +DOUBLEEXTENDS = '''\ +{% extends "layout" %} +{% extends "layout" %} +{% block block1 %} + {% if false %} + {% block block2 %} + this should workd + {% endblock %} + {% endif %} +{% endblock %} +''' + + +env = Environment(loader=DictLoader({ + 'layout': LAYOUTTEMPLATE, + 'level1': LEVEL1TEMPLATE, + 'level2': LEVEL2TEMPLATE, + 'level3': LEVEL3TEMPLATE, + 'level4': LEVEL4TEMPLATE, + 'working': WORKINGTEMPLATE, + 'doublee': DOUBLEEXTENDS, +}), trim_blocks=True) + + +class InheritanceTestCase(JinjaTestCase): + + def test_layout(self): + tmpl = env.get_template('layout') + assert tmpl.render() == ('|block 1 from layout|block 2 from ' + 'layout|nested block 4 from layout|') + + def test_level1(self): + tmpl = env.get_template('level1') + assert tmpl.render() == ('|block 1 from level1|block 2 from ' + 'layout|nested block 4 from layout|') + + def test_level2(self): + tmpl = env.get_template('level2') + assert tmpl.render() == ('|block 1 from level1|nested block 5 from ' + 'level2|nested block 4 from layout|') + + def test_level3(self): + tmpl = env.get_template('level3') + assert tmpl.render() == ('|block 1 from level1|block 5 from level3|' + 'block 4 from level3|') + + def test_level4(sel): + tmpl = env.get_template('level4') + assert tmpl.render() == ('|block 1 from level1|block 5 from ' + 'level3|block 3 from level4|') + + def test_super(self): + env = Environment(loader=DictLoader({ + 'a': '{% block intro %}INTRO{% endblock %}|' + 'BEFORE|{% block data %}INNER{% endblock %}|AFTER', + 'b': '{% extends "a" %}{% block data %}({{ ' + 'super() }}){% endblock %}', + 'c': '{% extends "b" %}{% block intro %}--{{ ' + 'super() }}--{% endblock %}\n{% block data ' + '%}[{{ super() }}]{% endblock %}' + })) + tmpl = env.get_template('c') + assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER' + + def test_working(self): + tmpl = env.get_template('working') + + def test_reuse_blocks(self): + tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42' + '{% endblock %}|{{ self.foo() }}') + assert tmpl.render() == '42|42|42' + + def test_preserve_blocks(self): + env = Environment(loader=DictLoader({ + 'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}', + 'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}' + })) + tmpl = env.get_template('b') + assert tmpl.render() == 'BA' + + def test_dynamic_inheritance(self): + env = Environment(loader=DictLoader({ + 'master1': 'MASTER1{% block x %}{% endblock %}', + 'master2': 'MASTER2{% block x %}{% endblock %}', + 'child': '{% extends master %}{% block x %}CHILD{% endblock %}' + })) + tmpl = env.get_template('child') + for m in range(1, 3): + assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m + + def test_multi_inheritance(self): + env = Environment(loader=DictLoader({ + 'master1': 'MASTER1{% block x %}{% endblock %}', + 'master2': 'MASTER2{% block x %}{% endblock %}', + 'child': '''{% if master %}{% extends master %}{% else %}{% extends + 'master1' %}{% endif %}{% block x %}CHILD{% endblock %}''' + })) + tmpl = env.get_template('child') + assert tmpl.render(master='master2') == 'MASTER2CHILD' + assert tmpl.render(master='master1') == 'MASTER1CHILD' + assert tmpl.render() == 'MASTER1CHILD' + + def test_scoped_block(self): + env = Environment(loader=DictLoader({ + 'master.html': '{% for item in seq %}[{% block item scoped %}' + '{% endblock %}]{% endfor %}' + })) + t = env.from_string('{% extends "master.html" %}{% block item %}' + '{{ item }}{% endblock %}') + assert t.render(seq=list(range(5))) == '[0][1][2][3][4]' + + def test_super_in_scoped_block(self): + env = Environment(loader=DictLoader({ + 'master.html': '{% for item in seq %}[{% block item scoped %}' + '{{ item }}{% endblock %}]{% endfor %}' + })) + t = env.from_string('{% extends "master.html" %}{% block item %}' + '{{ super() }}|{{ item * 2 }}{% endblock %}') + assert t.render(seq=list(range(5))) == '[0|0][1|2][2|4][3|6][4|8]' + + def test_scoped_block_after_inheritance(self): + env = Environment(loader=DictLoader({ + 'layout.html': ''' + {% block useless %}{% endblock %} + ''', + 'index.html': ''' + {%- extends 'layout.html' %} + {% from 'helpers.html' import foo with context %} + {% block useless %} + {% for x in [1, 2, 3] %} + {% block testing scoped %} + {{ foo(x) }} + {% endblock %} + {% endfor %} + {% endblock %} + ''', + 'helpers.html': ''' + {% macro foo(x) %}{{ the_foo + x }}{% endmacro %} + ''' + })) + rv = env.get_template('index.html').render(the_foo=42).split() + assert rv == ['43', '44', '45'] + + +class BugFixTestCase(JinjaTestCase): + + def test_fixed_macro_scoping_bug(self): + assert Environment(loader=DictLoader({ + 'test.html': '''\ + {% extends 'details.html' %} + + {% macro my_macro() %} + my_macro + {% endmacro %} + + {% block inner_box %} + {{ my_macro() }} + {% endblock %} + ''', + 'details.html': '''\ + {% extends 'standard.html' %} + + {% macro my_macro() %} + my_macro + {% endmacro %} + + {% block content %} + {% block outer_box %} + outer_box + {% block inner_box %} + inner_box + {% endblock %} + {% endblock %} + {% endblock %} + ''', + 'standard.html': ''' + {% block content %} {% endblock %} + ''' + })).get_template("test.html").render().split() == [u'outer_box', u'my_macro'] + + def test_double_extends(self): + """Ensures that a template with more than 1 {% extends ... %} usage + raises a ``TemplateError``. + """ + try: + tmpl = env.get_template('doublee') + except Exception as e: + assert isinstance(e, TemplateError) + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(InheritanceTestCase)) + suite.addTest(unittest.makeSuite(BugFixTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/lexnparse.py b/module/lib/jinja2/testsuite/lexnparse.py new file mode 100644 index 000000000..bd1c94cd3 --- /dev/null +++ b/module/lib/jinja2/testsuite/lexnparse.py @@ -0,0 +1,593 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.lexnparse + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + All the unittests regarding lexing, parsing and syntax. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Environment, Template, TemplateSyntaxError, \ + UndefinedError, nodes +from jinja2._compat import next, iteritems, text_type, PY2 +from jinja2.lexer import Token, TokenStream, TOKEN_EOF, \ + TOKEN_BLOCK_BEGIN, TOKEN_BLOCK_END + +env = Environment() + + +# how does a string look like in jinja syntax? +if PY2: + def jinja_string_repr(string): + return repr(string)[1:] +else: + jinja_string_repr = repr + + +class TokenStreamTestCase(JinjaTestCase): + test_tokens = [Token(1, TOKEN_BLOCK_BEGIN, ''), + Token(2, TOKEN_BLOCK_END, ''), + ] + + def test_simple(self): + ts = TokenStream(self.test_tokens, "foo", "bar") + assert ts.current.type is TOKEN_BLOCK_BEGIN + assert bool(ts) + assert not bool(ts.eos) + next(ts) + assert ts.current.type is TOKEN_BLOCK_END + assert bool(ts) + assert not bool(ts.eos) + next(ts) + assert ts.current.type is TOKEN_EOF + assert not bool(ts) + assert bool(ts.eos) + + def test_iter(self): + token_types = [t.type for t in TokenStream(self.test_tokens, "foo", "bar")] + assert token_types == ['block_begin', 'block_end', ] + + +class LexerTestCase(JinjaTestCase): + + def test_raw1(self): + tmpl = env.from_string('{% raw %}foo{% endraw %}|' + '{%raw%}{{ bar }}|{% baz %}{% endraw %}') + assert tmpl.render() == 'foo|{{ bar }}|{% baz %}' + + def test_raw2(self): + tmpl = env.from_string('1 {%- raw -%} 2 {%- endraw -%} 3') + assert tmpl.render() == '123' + + def test_balancing(self): + env = Environment('{%', '%}', '${', '}') + tmpl = env.from_string('''{% for item in seq + %}${{'foo': item}|upper}{% endfor %}''') + assert tmpl.render(seq=list(range(3))) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}" + + def test_comments(self): + env = Environment('<!--', '-->', '{', '}') + tmpl = env.from_string('''\ +<ul> +<!--- for item in seq --> + <li>{item}</li> +<!--- endfor --> +</ul>''') + assert tmpl.render(seq=list(range(3))) == ("<ul>\n <li>0</li>\n " + "<li>1</li>\n <li>2</li>\n</ul>") + + def test_string_escapes(self): + for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n': + tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char)) + assert tmpl.render() == char + assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668' + + def test_bytefallback(self): + from pprint import pformat + tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bÀr'|pprint }}''') + assert tmpl.render() == pformat('foo') + '|' + pformat(u'bÀr') + + def test_operators(self): + from jinja2.lexer import operators + for test, expect in iteritems(operators): + if test in '([{}])': + continue + stream = env.lexer.tokenize('{{ %s }}' % test) + next(stream) + assert stream.current.type == expect + + def test_normalizing(self): + for seq in '\r', '\r\n', '\n': + env = Environment(newline_sequence=seq) + tmpl = env.from_string('1\n2\r\n3\n4\n') + result = tmpl.render() + assert result.replace(seq, 'X') == '1X2X3X4' + + def test_trailing_newline(self): + for keep in [True, False]: + env = Environment(keep_trailing_newline=keep) + for template,expected in [ + ('', {}), + ('no\nnewline', {}), + ('with\nnewline\n', {False: 'with\nnewline'}), + ('with\nseveral\n\n\n', {False: 'with\nseveral\n\n'}), + ]: + tmpl = env.from_string(template) + expect = expected.get(keep, template) + result = tmpl.render() + assert result == expect, (keep, template, result, expect) + +class ParserTestCase(JinjaTestCase): + + def test_php_syntax(self): + env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->') + tmpl = env.from_string('''\ +<!-- I'm a comment, I'm not interesting -->\ +<? for item in seq -?> + <?= item ?> +<?- endfor ?>''') + assert tmpl.render(seq=list(range(5))) == '01234' + + def test_erb_syntax(self): + env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>') + tmpl = env.from_string('''\ +<%# I'm a comment, I'm not interesting %>\ +<% for item in seq -%> + <%= item %> +<%- endfor %>''') + assert tmpl.render(seq=list(range(5))) == '01234' + + def test_comment_syntax(self): + env = Environment('<!--', '-->', '${', '}', '<!--#', '-->') + tmpl = env.from_string('''\ +<!--# I'm a comment, I'm not interesting -->\ +<!-- for item in seq ---> + ${item} +<!--- endfor -->''') + assert tmpl.render(seq=list(range(5))) == '01234' + + def test_balancing(self): + tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''') + assert tmpl.render() == 'bar' + + def test_start_comment(self): + tmpl = env.from_string('''{# foo comment +and bar comment #} +{% macro blub() %}foo{% endmacro %} +{{ blub() }}''') + assert tmpl.render().strip() == 'foo' + + def test_line_syntax(self): + env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%') + tmpl = env.from_string('''\ +<%# regular comment %> +% for item in seq: + ${item} +% endfor''') + assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \ + list(range(5)) + + env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##') + tmpl = env.from_string('''\ +<%# regular comment %> +% for item in seq: + ${item} ## the rest of the stuff +% endfor''') + assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \ + list(range(5)) + + def test_line_syntax_priority(self): + # XXX: why is the whitespace there in front of the newline? + env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#') + tmpl = env.from_string('''\ +/* ignore me. + I'm a multiline comment */ +## for item in seq: +* ${item} # this is just extra stuff +## endfor''') + assert tmpl.render(seq=[1, 2]).strip() == '* 1\n* 2' + env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##') + tmpl = env.from_string('''\ +/* ignore me. + I'm a multiline comment */ +# for item in seq: +* ${item} ## this is just extra stuff + ## extra stuff i just want to ignore +# endfor''') + assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2' + + def test_error_messages(self): + def assert_error(code, expected): + try: + Template(code) + except TemplateSyntaxError as e: + assert str(e) == expected, 'unexpected error message' + else: + assert False, 'that was supposed to be an error' + + assert_error('{% for item in seq %}...{% endif %}', + "Encountered unknown tag 'endif'. Jinja was looking " + "for the following tags: 'endfor' or 'else'. The " + "innermost block that needs to be closed is 'for'.") + assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}', + "Encountered unknown tag 'endfor'. Jinja was looking for " + "the following tags: 'elif' or 'else' or 'endif'. The " + "innermost block that needs to be closed is 'if'.") + assert_error('{% if foo %}', + "Unexpected end of template. Jinja was looking for the " + "following tags: 'elif' or 'else' or 'endif'. The " + "innermost block that needs to be closed is 'if'.") + assert_error('{% for item in seq %}', + "Unexpected end of template. Jinja was looking for the " + "following tags: 'endfor' or 'else'. The innermost block " + "that needs to be closed is 'for'.") + assert_error('{% block foo-bar-baz %}', + "Block names in Jinja have to be valid Python identifiers " + "and may not contain hyphens, use an underscore instead.") + assert_error('{% unknown_tag %}', + "Encountered unknown tag 'unknown_tag'.") + + +class SyntaxTestCase(JinjaTestCase): + + def test_call(self): + env = Environment() + env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g + tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}") + assert tmpl.render() == 'abdfh' + + def test_slicing(self): + tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}') + assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]' + + def test_attr(self): + tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}") + assert tmpl.render(foo={'bar': 42}) == '42|42' + + def test_subscript(self): + tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}") + assert tmpl.render(foo=[0, 1, 2]) == '0|2' + + def test_tuple(self): + tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}') + assert tmpl.render() == '()|(1,)|(1, 2)' + + def test_math(self): + tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}') + assert tmpl.render() == '1.5|8' + + def test_div(self): + tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}') + assert tmpl.render() == '1|1.5|1' + + def test_unary(self): + tmpl = env.from_string('{{ +3 }}|{{ -3 }}') + assert tmpl.render() == '3|-3' + + def test_concat(self): + tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}") + assert tmpl.render() == '[1, 2]foo' + + def test_compare(self): + tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|' + '{{ 2 == 2 }}|{{ 1 <= 1 }}') + assert tmpl.render() == 'True|True|True|True|True' + + def test_inop(self): + tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}') + assert tmpl.render() == 'True|False' + + def test_literals(self): + tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}') + assert tmpl.render().lower() == '[]|{}|()' + + def test_bool(self): + tmpl = env.from_string('{{ true and false }}|{{ false ' + 'or true }}|{{ not false }}') + assert tmpl.render() == 'False|True|True' + + def test_grouping(self): + tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}') + assert tmpl.render() == 'False' + + def test_django_attr(self): + tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}') + assert tmpl.render() == '1|1' + + def test_conditional_expression(self): + tmpl = env.from_string('''{{ 0 if true else 1 }}''') + assert tmpl.render() == '0' + + def test_short_conditional_expression(self): + tmpl = env.from_string('<{{ 1 if false }}>') + assert tmpl.render() == '<>' + + tmpl = env.from_string('<{{ (1 if false).bar }}>') + self.assert_raises(UndefinedError, tmpl.render) + + def test_filter_priority(self): + tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}') + assert tmpl.render() == 'FOOBAR' + + def test_function_calls(self): + tests = [ + (True, '*foo, bar'), + (True, '*foo, *bar'), + (True, '*foo, bar=42'), + (True, '**foo, *bar'), + (True, '**foo, bar'), + (False, 'foo, bar'), + (False, 'foo, bar=42'), + (False, 'foo, bar=23, *args'), + (False, 'a, b=c, *d, **e'), + (False, '*foo, **bar') + ] + for should_fail, sig in tests: + if should_fail: + self.assert_raises(TemplateSyntaxError, + env.from_string, '{{ foo(%s) }}' % sig) + else: + env.from_string('foo(%s)' % sig) + + def test_tuple_expr(self): + for tmpl in [ + '{{ () }}', + '{{ (1, 2) }}', + '{{ (1, 2,) }}', + '{{ 1, }}', + '{{ 1, 2 }}', + '{% for foo, bar in seq %}...{% endfor %}', + '{% for x in foo, bar %}...{% endfor %}', + '{% for x in foo, %}...{% endfor %}' + ]: + assert env.from_string(tmpl) + + def test_trailing_comma(self): + tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}') + assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}' + + def test_block_end_name(self): + env.from_string('{% block foo %}...{% endblock foo %}') + self.assert_raises(TemplateSyntaxError, env.from_string, + '{% block x %}{% endblock y %}') + + def test_constant_casing(self): + for const in True, False, None: + tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % ( + str(const), str(const).lower(), str(const).upper() + )) + assert tmpl.render() == '%s|%s|' % (const, const) + + def test_test_chaining(self): + self.assert_raises(TemplateSyntaxError, env.from_string, + '{{ foo is string is sequence }}') + assert env.from_string('{{ 42 is string or 42 is number }}' + ).render() == 'True' + + def test_string_concatenation(self): + tmpl = env.from_string('{{ "foo" "bar" "baz" }}') + assert tmpl.render() == 'foobarbaz' + + def test_notin(self): + bar = range(100) + tmpl = env.from_string('''{{ not 42 in bar }}''') + assert tmpl.render(bar=bar) == text_type(not 42 in bar) + + def test_implicit_subscribed_tuple(self): + class Foo(object): + def __getitem__(self, x): + return x + t = env.from_string('{{ foo[1, 2] }}') + assert t.render(foo=Foo()) == u'(1, 2)' + + def test_raw2(self): + tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}') + assert tmpl.render() == '{{ FOO }} and {% BAR %}' + + def test_const(self): + tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|' + '{{ none is defined }}|{{ missing is defined }}') + assert tmpl.render() == 'True|False|None|True|False' + + def test_neg_filter_priority(self): + node = env.parse('{{ -1|foo }}') + assert isinstance(node.body[0].nodes[0], nodes.Filter) + assert isinstance(node.body[0].nodes[0].node, nodes.Neg) + + def test_const_assign(self): + constass1 = '''{% set true = 42 %}''' + constass2 = '''{% for none in seq %}{% endfor %}''' + for tmpl in constass1, constass2: + self.assert_raises(TemplateSyntaxError, env.from_string, tmpl) + + def test_localset(self): + tmpl = env.from_string('''{% set foo = 0 %}\ +{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\ +{{ foo }}''') + assert tmpl.render() == '0' + + def test_parse_unary(self): + tmpl = env.from_string('{{ -foo["bar"] }}') + assert tmpl.render(foo={'bar': 42}) == '-42' + tmpl = env.from_string('{{ -foo["bar"]|abs }}') + assert tmpl.render(foo={'bar': 42}) == '42' + + +class LstripBlocksTestCase(JinjaTestCase): + + def test_lstrip(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' {% if True %}\n {% endif %}''') + assert tmpl.render() == "\n" + + def test_lstrip_trim(self): + env = Environment(lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string(''' {% if True %}\n {% endif %}''') + assert tmpl.render() == "" + + def test_no_lstrip(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' {%+ if True %}\n {%+ endif %}''') + assert tmpl.render() == " \n " + + def test_lstrip_endline(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' hello{% if True %}\n goodbye{% endif %}''') + assert tmpl.render() == " hello\n goodbye" + + def test_lstrip_inline(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' {% if True %}hello {% endif %}''') + assert tmpl.render() == 'hello ' + + def test_lstrip_nested(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' {% if True %}a {% if True %}b {% endif %}c {% endif %}''') + assert tmpl.render() == 'a b c ' + + def test_lstrip_left_chars(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' abc {% if True %} + hello{% endif %}''') + assert tmpl.render() == ' abc \n hello' + + def test_lstrip_embeded_strings(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' {% set x = " {% str %} " %}{{ x }}''') + assert tmpl.render() == ' {% str %} ' + + def test_lstrip_preserve_leading_newlines(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string('''\n\n\n{% set hello = 1 %}''') + assert tmpl.render() == '\n\n\n' + + def test_lstrip_comment(self): + env = Environment(lstrip_blocks=True, trim_blocks=False) + tmpl = env.from_string(''' {# if True #} +hello + {#endif#}''') + assert tmpl.render() == '\nhello\n' + + def test_lstrip_angle_bracket_simple(self): + env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string(''' <% if True %>hello <% endif %>''') + assert tmpl.render() == 'hello ' + + def test_lstrip_angle_bracket_comment(self): + env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string(''' <%# if True %>hello <%# endif %>''') + assert tmpl.render() == 'hello ' + + def test_lstrip_angle_bracket(self): + env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ + <%# regular comment %> + <% for item in seq %> +${item} ## the rest of the stuff + <% endfor %>''') + assert tmpl.render(seq=range(5)) == \ + ''.join('%s\n' % x for x in range(5)) + + def test_lstrip_angle_bracket_compact(self): + env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ + <%#regular comment%> + <%for item in seq%> +${item} ## the rest of the stuff + <%endfor%>''') + assert tmpl.render(seq=range(5)) == \ + ''.join('%s\n' % x for x in range(5)) + + def test_php_syntax_with_manual(self): + env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ + <!-- I'm a comment, I'm not interesting --> + <? for item in seq -?> + <?= item ?> + <?- endfor ?>''') + assert tmpl.render(seq=range(5)) == '01234' + + def test_php_syntax(self): + env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ + <!-- I'm a comment, I'm not interesting --> + <? for item in seq ?> + <?= item ?> + <? endfor ?>''') + assert tmpl.render(seq=range(5)) == ''.join(' %s\n' % x for x in range(5)) + + def test_php_syntax_compact(self): + env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ + <!-- I'm a comment, I'm not interesting --> + <?for item in seq?> + <?=item?> + <?endfor?>''') + assert tmpl.render(seq=range(5)) == ''.join(' %s\n' % x for x in range(5)) + + def test_erb_syntax(self): + env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>', + lstrip_blocks=True, trim_blocks=True) + #env.from_string('') + #for n,r in env.lexer.rules.iteritems(): + # print n + #print env.lexer.rules['root'][0][0].pattern + #print "'%s'" % tmpl.render(seq=range(5)) + tmpl = env.from_string('''\ +<%# I'm a comment, I'm not interesting %> + <% for item in seq %> + <%= item %> + <% endfor %> +''') + assert tmpl.render(seq=range(5)) == ''.join(' %s\n' % x for x in range(5)) + + def test_erb_syntax_with_manual(self): + env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ +<%# I'm a comment, I'm not interesting %> + <% for item in seq -%> + <%= item %> + <%- endfor %>''') + assert tmpl.render(seq=range(5)) == '01234' + + def test_erb_syntax_no_lstrip(self): + env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ +<%# I'm a comment, I'm not interesting %> + <%+ for item in seq -%> + <%= item %> + <%- endfor %>''') + assert tmpl.render(seq=range(5)) == ' 01234' + + def test_comment_syntax(self): + env = Environment('<!--', '-->', '${', '}', '<!--#', '-->', + lstrip_blocks=True, trim_blocks=True) + tmpl = env.from_string('''\ +<!--# I'm a comment, I'm not interesting -->\ +<!-- for item in seq ---> + ${item} +<!--- endfor -->''') + assert tmpl.render(seq=range(5)) == '01234' + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TokenStreamTestCase)) + suite.addTest(unittest.makeSuite(LexerTestCase)) + suite.addTest(unittest.makeSuite(ParserTestCase)) + suite.addTest(unittest.makeSuite(SyntaxTestCase)) + suite.addTest(unittest.makeSuite(LstripBlocksTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/loader.py b/module/lib/jinja2/testsuite/loader.py new file mode 100644 index 000000000..a7350aab9 --- /dev/null +++ b/module/lib/jinja2/testsuite/loader.py @@ -0,0 +1,226 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.loader + ~~~~~~~~~~~~~~~~~~~~~~~ + + Test the loaders. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import os +import sys +import tempfile +import shutil +import unittest + +from jinja2.testsuite import JinjaTestCase, dict_loader, \ + package_loader, filesystem_loader, function_loader, \ + choice_loader, prefix_loader + +from jinja2 import Environment, loaders +from jinja2._compat import PYPY, PY2 +from jinja2.loaders import split_template_path +from jinja2.exceptions import TemplateNotFound + + +class LoaderTestCase(JinjaTestCase): + + def test_dict_loader(self): + env = Environment(loader=dict_loader) + tmpl = env.get_template('justdict.html') + assert tmpl.render().strip() == 'FOO' + self.assert_raises(TemplateNotFound, env.get_template, 'missing.html') + + def test_package_loader(self): + env = Environment(loader=package_loader) + tmpl = env.get_template('test.html') + assert tmpl.render().strip() == 'BAR' + self.assert_raises(TemplateNotFound, env.get_template, 'missing.html') + + def test_filesystem_loader(self): + env = Environment(loader=filesystem_loader) + tmpl = env.get_template('test.html') + assert tmpl.render().strip() == 'BAR' + tmpl = env.get_template('foo/test.html') + assert tmpl.render().strip() == 'FOO' + self.assert_raises(TemplateNotFound, env.get_template, 'missing.html') + + def test_choice_loader(self): + env = Environment(loader=choice_loader) + tmpl = env.get_template('justdict.html') + assert tmpl.render().strip() == 'FOO' + tmpl = env.get_template('test.html') + assert tmpl.render().strip() == 'BAR' + self.assert_raises(TemplateNotFound, env.get_template, 'missing.html') + + def test_function_loader(self): + env = Environment(loader=function_loader) + tmpl = env.get_template('justfunction.html') + assert tmpl.render().strip() == 'FOO' + self.assert_raises(TemplateNotFound, env.get_template, 'missing.html') + + def test_prefix_loader(self): + env = Environment(loader=prefix_loader) + tmpl = env.get_template('a/test.html') + assert tmpl.render().strip() == 'BAR' + tmpl = env.get_template('b/justdict.html') + assert tmpl.render().strip() == 'FOO' + self.assert_raises(TemplateNotFound, env.get_template, 'missing') + + def test_caching(self): + changed = False + class TestLoader(loaders.BaseLoader): + def get_source(self, environment, template): + return u'foo', None, lambda: not changed + env = Environment(loader=TestLoader(), cache_size=-1) + tmpl = env.get_template('template') + assert tmpl is env.get_template('template') + changed = True + assert tmpl is not env.get_template('template') + changed = False + + env = Environment(loader=TestLoader(), cache_size=0) + assert env.get_template('template') \ + is not env.get_template('template') + + env = Environment(loader=TestLoader(), cache_size=2) + t1 = env.get_template('one') + t2 = env.get_template('two') + assert t2 is env.get_template('two') + assert t1 is env.get_template('one') + t3 = env.get_template('three') + assert 'one' in env.cache + assert 'two' not in env.cache + assert 'three' in env.cache + + def test_dict_loader_cache_invalidates(self): + mapping = {'foo': "one"} + env = Environment(loader=loaders.DictLoader(mapping)) + assert env.get_template('foo').render() == "one" + mapping['foo'] = "two" + assert env.get_template('foo').render() == "two" + + def test_split_template_path(self): + assert split_template_path('foo/bar') == ['foo', 'bar'] + assert split_template_path('./foo/bar') == ['foo', 'bar'] + self.assert_raises(TemplateNotFound, split_template_path, '../foo') + + +class ModuleLoaderTestCase(JinjaTestCase): + archive = None + + def compile_down(self, zip='deflated', py_compile=False): + super(ModuleLoaderTestCase, self).setup() + log = [] + self.reg_env = Environment(loader=prefix_loader) + if zip is not None: + self.archive = tempfile.mkstemp(suffix='.zip')[1] + else: + self.archive = tempfile.mkdtemp() + self.reg_env.compile_templates(self.archive, zip=zip, + log_function=log.append, + py_compile=py_compile) + self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive)) + return ''.join(log) + + def teardown(self): + super(ModuleLoaderTestCase, self).teardown() + if hasattr(self, 'mod_env'): + if os.path.isfile(self.archive): + os.remove(self.archive) + else: + shutil.rmtree(self.archive) + self.archive = None + + def test_log(self): + log = self.compile_down() + assert 'Compiled "a/foo/test.html" as ' \ + 'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log + assert 'Finished compiling templates' in log + assert 'Could not compile "a/syntaxerror.html": ' \ + 'Encountered unknown tag \'endif\'' in log + + def _test_common(self): + tmpl1 = self.reg_env.get_template('a/test.html') + tmpl2 = self.mod_env.get_template('a/test.html') + assert tmpl1.render() == tmpl2.render() + + tmpl1 = self.reg_env.get_template('b/justdict.html') + tmpl2 = self.mod_env.get_template('b/justdict.html') + assert tmpl1.render() == tmpl2.render() + + def test_deflated_zip_compile(self): + self.compile_down(zip='deflated') + self._test_common() + + def test_stored_zip_compile(self): + self.compile_down(zip='stored') + self._test_common() + + def test_filesystem_compile(self): + self.compile_down(zip=None) + self._test_common() + + def test_weak_references(self): + self.compile_down() + tmpl = self.mod_env.get_template('a/test.html') + key = loaders.ModuleLoader.get_template_key('a/test.html') + name = self.mod_env.loader.module.__name__ + + assert hasattr(self.mod_env.loader.module, key) + assert name in sys.modules + + # unset all, ensure the module is gone from sys.modules + self.mod_env = tmpl = None + + try: + import gc + gc.collect() + except: + pass + + assert name not in sys.modules + + # This test only makes sense on non-pypy python 2 + if PY2 and not PYPY: + def test_byte_compilation(self): + log = self.compile_down(py_compile=True) + assert 'Byte-compiled "a/test.html"' in log + tmpl1 = self.mod_env.get_template('a/test.html') + mod = self.mod_env.loader.module. \ + tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490 + assert mod.__file__.endswith('.pyc') + + def test_choice_loader(self): + log = self.compile_down() + + self.mod_env.loader = loaders.ChoiceLoader([ + self.mod_env.loader, + loaders.DictLoader({'DICT_SOURCE': 'DICT_TEMPLATE'}) + ]) + + tmpl1 = self.mod_env.get_template('a/test.html') + self.assert_equal(tmpl1.render(), 'BAR') + tmpl2 = self.mod_env.get_template('DICT_SOURCE') + self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE') + + def test_prefix_loader(self): + log = self.compile_down() + + self.mod_env.loader = loaders.PrefixLoader({ + 'MOD': self.mod_env.loader, + 'DICT': loaders.DictLoader({'test.html': 'DICT_TEMPLATE'}) + }) + + tmpl1 = self.mod_env.get_template('MOD/a/test.html') + self.assert_equal(tmpl1.render(), 'BAR') + tmpl2 = self.mod_env.get_template('DICT/test.html') + self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE') + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(LoaderTestCase)) + suite.addTest(unittest.makeSuite(ModuleLoaderTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/regression.py b/module/lib/jinja2/testsuite/regression.py new file mode 100644 index 000000000..c5f7d5c65 --- /dev/null +++ b/module/lib/jinja2/testsuite/regression.py @@ -0,0 +1,279 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.regression + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Tests corner cases and bugs. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \ + TemplateNotFound, PrefixLoader +from jinja2._compat import text_type + +env = Environment() + + +class CornerTestCase(JinjaTestCase): + + def test_assigned_scoping(self): + t = env.from_string(''' + {%- for item in (1, 2, 3, 4) -%} + [{{ item }}] + {%- endfor %} + {{- item -}} + ''') + assert t.render(item=42) == '[1][2][3][4]42' + + t = env.from_string(''' + {%- for item in (1, 2, 3, 4) -%} + [{{ item }}] + {%- endfor %} + {%- set item = 42 %} + {{- item -}} + ''') + assert t.render() == '[1][2][3][4]42' + + t = env.from_string(''' + {%- set item = 42 %} + {%- for item in (1, 2, 3, 4) -%} + [{{ item }}] + {%- endfor %} + {{- item -}} + ''') + assert t.render() == '[1][2][3][4]42' + + def test_closure_scoping(self): + t = env.from_string(''' + {%- set wrapper = "<FOO>" %} + {%- for item in (1, 2, 3, 4) %} + {%- macro wrapper() %}[{{ item }}]{% endmacro %} + {{- wrapper() }} + {%- endfor %} + {{- wrapper -}} + ''') + assert t.render() == '[1][2][3][4]<FOO>' + + t = env.from_string(''' + {%- for item in (1, 2, 3, 4) %} + {%- macro wrapper() %}[{{ item }}]{% endmacro %} + {{- wrapper() }} + {%- endfor %} + {%- set wrapper = "<FOO>" %} + {{- wrapper -}} + ''') + assert t.render() == '[1][2][3][4]<FOO>' + + t = env.from_string(''' + {%- for item in (1, 2, 3, 4) %} + {%- macro wrapper() %}[{{ item }}]{% endmacro %} + {{- wrapper() }} + {%- endfor %} + {{- wrapper -}} + ''') + assert t.render(wrapper=23) == '[1][2][3][4]23' + + +class BugTestCase(JinjaTestCase): + + def test_keyword_folding(self): + env = Environment() + env.filters['testing'] = lambda value, some: value + some + assert env.from_string("{{ 'test'|testing(some='stuff') }}") \ + .render() == 'teststuff' + + def test_extends_output_bugs(self): + env = Environment(loader=DictLoader({ + 'parent.html': '(({% block title %}{% endblock %}))' + })) + + t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}' + '[[{% block title %}title{% endblock %}]]' + '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}') + assert t.render(expr=False) == '[[title]](1)(2)(3)' + assert t.render(expr=True) == '((title))' + + def test_urlize_filter_escaping(self): + tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}') + assert tmpl.render() == '<a href="http://www.example.org/<foo">http://www.example.org/<foo</a>' + + def test_loop_call_loop(self): + tmpl = env.from_string(''' + + {% macro test() %} + {{ caller() }} + {% endmacro %} + + {% for num1 in range(5) %} + {% call test() %} + {% for num2 in range(10) %} + {{ loop.index }} + {% endfor %} + {% endcall %} + {% endfor %} + + ''') + + assert tmpl.render().split() == [text_type(x) for x in range(1, 11)] * 5 + + def test_weird_inline_comment(self): + env = Environment(line_statement_prefix='%') + self.assert_raises(TemplateSyntaxError, env.from_string, + '% for item in seq {# missing #}\n...% endfor') + + def test_old_macro_loop_scoping_bug(self): + tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}' + '{% macro i() %}3{% endmacro %}{{ i() }}') + assert tmpl.render() == '123' + + def test_partial_conditional_assignments(self): + tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}') + assert tmpl.render(a=23) == '23' + assert tmpl.render(b=True) == '42' + + def test_stacked_locals_scoping_bug(self): + env = Environment(line_statement_prefix='#') + t = env.from_string('''\ +# for j in [1, 2]: +# set x = 1 +# for i in [1, 2]: +# print x +# if i % 2 == 0: +# set x = x + 1 +# endif +# endfor +# endfor +# if a +# print 'A' +# elif b +# print 'B' +# elif c == d +# print 'C' +# else +# print 'D' +# endif + ''') + assert t.render(a=0, b=False, c=42, d=42.0) == '1111C' + + def test_stacked_locals_scoping_bug_twoframe(self): + t = Template(''' + {% set x = 1 %} + {% for item in foo %} + {% if item == 1 %} + {% set x = 2 %} + {% endif %} + {% endfor %} + {{ x }} + ''') + rv = t.render(foo=[1]).strip() + assert rv == u'1' + + def test_call_with_args(self): + t = Template("""{% macro dump_users(users) -%} + <ul> + {%- for user in users -%} + <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li> + {%- endfor -%} + </ul> + {%- endmacro -%} + + {% call(user) dump_users(list_of_user) -%} + <dl> + <dl>Realname</dl> + <dd>{{ user.realname|e }}</dd> + <dl>Description</dl> + <dd>{{ user.description }}</dd> + </dl> + {% endcall %}""") + + assert [x.strip() for x in t.render(list_of_user=[{ + 'username':'apo', + 'realname':'something else', + 'description':'test' + }]).splitlines()] == [ + u'<ul><li><p>apo</p><dl>', + u'<dl>Realname</dl>', + u'<dd>something else</dd>', + u'<dl>Description</dl>', + u'<dd>test</dd>', + u'</dl>', + u'</li></ul>' + ] + + def test_empty_if_condition_fails(self): + self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}') + self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}') + self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}') + + def test_recursive_loop_bug(self): + tpl1 = Template(""" + {% for p in foo recursive%} + {{p.bar}} + {% for f in p.fields recursive%} + {{f.baz}} + {{p.bar}} + {% if f.rec %} + {{ loop(f.sub) }} + {% endif %} + {% endfor %} + {% endfor %} + """) + + tpl2 = Template(""" + {% for p in foo%} + {{p.bar}} + {% for f in p.fields recursive%} + {{f.baz}} + {{p.bar}} + {% if f.rec %} + {{ loop(f.sub) }} + {% endif %} + {% endfor %} + {% endfor %} + """) + + def test_else_loop_bug(self): + t = Template(''' + {% for x in y %} + {{ loop.index0 }} + {% else %} + {% for i in range(3) %}{{ i }}{% endfor %} + {% endfor %} + ''') + self.assertEqual(t.render(y=[]).strip(), '012') + + def test_correct_prefix_loader_name(self): + env = Environment(loader=PrefixLoader({ + 'foo': DictLoader({}) + })) + try: + env.get_template('foo/bar.html') + except TemplateNotFound as e: + assert e.name == 'foo/bar.html' + else: + assert False, 'expected error here' + + def test_contextfunction_callable_classes(self): + from jinja2.utils import contextfunction + class CallableClass(object): + @contextfunction + def __call__(self, ctx): + return ctx.resolve('hello') + + tpl = Template("""{{ callableclass() }}""") + output = tpl.render(callableclass = CallableClass(), hello = 'TEST') + expected = 'TEST' + + self.assert_equal(output, expected) + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(CornerTestCase)) + suite.addTest(unittest.makeSuite(BugTestCase)) + return suite diff --git a/module/plugins/captcha/__init__.py b/module/lib/jinja2/testsuite/res/__init__.py index e69de29bb..e69de29bb 100644 --- a/module/plugins/captcha/__init__.py +++ b/module/lib/jinja2/testsuite/res/__init__.py diff --git a/module/lib/jinja2/testsuite/res/templates/broken.html b/module/lib/jinja2/testsuite/res/templates/broken.html new file mode 100644 index 000000000..77669fae5 --- /dev/null +++ b/module/lib/jinja2/testsuite/res/templates/broken.html @@ -0,0 +1,3 @@ +Before +{{ fail() }} +After diff --git a/module/lib/jinja2/testsuite/res/templates/foo/test.html b/module/lib/jinja2/testsuite/res/templates/foo/test.html new file mode 100644 index 000000000..b7d6715e2 --- /dev/null +++ b/module/lib/jinja2/testsuite/res/templates/foo/test.html @@ -0,0 +1 @@ +FOO diff --git a/module/lib/jinja2/testsuite/res/templates/syntaxerror.html b/module/lib/jinja2/testsuite/res/templates/syntaxerror.html new file mode 100644 index 000000000..f21b81793 --- /dev/null +++ b/module/lib/jinja2/testsuite/res/templates/syntaxerror.html @@ -0,0 +1,4 @@ +Foo +{% for item in broken %} + ... +{% endif %} diff --git a/module/lib/jinja2/testsuite/res/templates/test.html b/module/lib/jinja2/testsuite/res/templates/test.html new file mode 100644 index 000000000..ba578e48b --- /dev/null +++ b/module/lib/jinja2/testsuite/res/templates/test.html @@ -0,0 +1 @@ +BAR diff --git a/module/lib/jinja2/testsuite/security.py b/module/lib/jinja2/testsuite/security.py new file mode 100644 index 000000000..246d0f073 --- /dev/null +++ b/module/lib/jinja2/testsuite/security.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.security + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Checks the sandbox and other security features. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Environment +from jinja2.sandbox import SandboxedEnvironment, \ + ImmutableSandboxedEnvironment, unsafe +from jinja2 import Markup, escape +from jinja2.exceptions import SecurityError, TemplateSyntaxError, \ + TemplateRuntimeError +from jinja2._compat import text_type + + +class PrivateStuff(object): + + def bar(self): + return 23 + + @unsafe + def foo(self): + return 42 + + def __repr__(self): + return 'PrivateStuff' + + +class PublicStuff(object): + bar = lambda self: 23 + _foo = lambda self: 42 + + def __repr__(self): + return 'PublicStuff' + + +class SandboxTestCase(JinjaTestCase): + + def test_unsafe(self): + env = SandboxedEnvironment() + self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render, + foo=PrivateStuff()) + self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23') + + self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render, + foo=PublicStuff()) + self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23') + self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '') + self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '') + # security error comes from __class__ already. + self.assert_raises(SecurityError, env.from_string( + "{{ foo.__class__.__subclasses__() }}").render, foo=42) + + def test_immutable_environment(self): + env = ImmutableSandboxedEnvironment() + self.assert_raises(SecurityError, env.from_string( + '{{ [].append(23) }}').render) + self.assert_raises(SecurityError, env.from_string( + '{{ {1:2}.clear() }}').render) + + def test_restricted(self): + env = SandboxedEnvironment() + self.assert_raises(TemplateSyntaxError, env.from_string, + "{% for item.attribute in seq %}...{% endfor %}") + self.assert_raises(TemplateSyntaxError, env.from_string, + "{% for foo, bar.baz in seq %}...{% endfor %}") + + def test_markup_operations(self): + # adding two strings should escape the unsafe one + unsafe = '<script type="application/x-some-script">alert("foo");</script>' + safe = Markup('<em>username</em>') + assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe) + + # string interpolations are safe to use too + assert Markup('<em>%s</em>') % '<bad user>' == \ + '<em><bad user></em>' + assert Markup('<em>%(username)s</em>') % { + 'username': '<bad user>' + } == '<em><bad user></em>' + + # an escaped object is markup too + assert type(Markup('foo') + 'bar') is Markup + + # and it implements __html__ by returning itself + x = Markup("foo") + assert x.__html__() is x + + # it also knows how to treat __html__ objects + class Foo(object): + def __html__(self): + return '<em>awesome</em>' + def __unicode__(self): + return 'awesome' + assert Markup(Foo()) == '<em>awesome</em>' + assert Markup('<strong>%s</strong>') % Foo() == \ + '<strong><em>awesome</em></strong>' + + # escaping and unescaping + assert escape('"<>&\'') == '"<>&'' + assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar" + assert Markup("<test>").unescape() == "<test>" + + def test_template_data(self): + env = Environment(autoescape=True) + t = env.from_string('{% macro say_hello(name) %}' + '<p>Hello {{ name }}!</p>{% endmacro %}' + '{{ say_hello("<blink>foo</blink>") }}') + escaped_out = '<p>Hello <blink>foo</blink>!</p>' + assert t.render() == escaped_out + assert text_type(t.module) == escaped_out + assert escape(t.module) == escaped_out + assert t.module.say_hello('<blink>foo</blink>') == escaped_out + assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out + + def test_attr_filter(self): + env = SandboxedEnvironment() + tmpl = env.from_string('{{ cls|attr("__subclasses__")() }}') + self.assert_raises(SecurityError, tmpl.render, cls=int) + + def test_binary_operator_intercepting(self): + def disable_op(left, right): + raise TemplateRuntimeError('that operator so does not work') + for expr, ctx, rv in ('1 + 2', {}, '3'), ('a + 2', {'a': 2}, '4'): + env = SandboxedEnvironment() + env.binop_table['+'] = disable_op + t = env.from_string('{{ %s }}' % expr) + assert t.render(ctx) == rv + env.intercepted_binops = frozenset(['+']) + t = env.from_string('{{ %s }}' % expr) + try: + t.render(ctx) + except TemplateRuntimeError as e: + pass + else: + self.fail('expected runtime error') + + def test_unary_operator_intercepting(self): + def disable_op(arg): + raise TemplateRuntimeError('that operator so does not work') + for expr, ctx, rv in ('-1', {}, '-1'), ('-a', {'a': 2}, '-2'): + env = SandboxedEnvironment() + env.unop_table['-'] = disable_op + t = env.from_string('{{ %s }}' % expr) + assert t.render(ctx) == rv + env.intercepted_unops = frozenset(['-']) + t = env.from_string('{{ %s }}' % expr) + try: + t.render(ctx) + except TemplateRuntimeError as e: + pass + else: + self.fail('expected runtime error') + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(SandboxTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/tests.py b/module/lib/jinja2/testsuite/tests.py new file mode 100644 index 000000000..3ece7a8ff --- /dev/null +++ b/module/lib/jinja2/testsuite/tests.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.tests + ~~~~~~~~~~~~~~~~~~~~~~ + + Who tests the tests? + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import unittest +from jinja2.testsuite import JinjaTestCase + +from jinja2 import Markup, Environment + +env = Environment() + + +class TestsTestCase(JinjaTestCase): + + def test_defined(self): + tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}') + assert tmpl.render() == 'False|True' + + def test_even(self): + tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''') + assert tmpl.render() == 'False|True' + + def test_odd(self): + tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''') + assert tmpl.render() == 'True|False' + + def test_lower(self): + tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''') + assert tmpl.render() == 'True|False' + + def test_typechecks(self): + tmpl = env.from_string(''' + {{ 42 is undefined }} + {{ 42 is defined }} + {{ 42 is none }} + {{ none is none }} + {{ 42 is number }} + {{ 42 is string }} + {{ "foo" is string }} + {{ "foo" is sequence }} + {{ [1] is sequence }} + {{ range is callable }} + {{ 42 is callable }} + {{ range(5) is iterable }} + {{ {} is mapping }} + {{ mydict is mapping }} + {{ [] is mapping }} + ''') + class MyDict(dict): + pass + assert tmpl.render(mydict=MyDict()).split() == [ + 'False', 'True', 'False', 'True', 'True', 'False', + 'True', 'True', 'True', 'True', 'False', 'True', + 'True', 'True', 'False' + ] + + def test_sequence(self): + tmpl = env.from_string( + '{{ [1, 2, 3] is sequence }}|' + '{{ "foo" is sequence }}|' + '{{ 42 is sequence }}' + ) + assert tmpl.render() == 'True|True|False' + + def test_upper(self): + tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}') + assert tmpl.render() == 'True|False' + + def test_sameas(self): + tmpl = env.from_string('{{ foo is sameas false }}|' + '{{ 0 is sameas false }}') + assert tmpl.render(foo=False) == 'True|False' + + def test_no_paren_for_arg1(self): + tmpl = env.from_string('{{ foo is sameas none }}') + assert tmpl.render(foo=None) == 'True' + + def test_escaped(self): + env = Environment(autoescape=True) + tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}') + assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True' + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestsTestCase)) + return suite diff --git a/module/lib/jinja2/testsuite/utils.py b/module/lib/jinja2/testsuite/utils.py new file mode 100644 index 000000000..cab9b09a9 --- /dev/null +++ b/module/lib/jinja2/testsuite/utils.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +""" + jinja2.testsuite.utils + ~~~~~~~~~~~~~~~~~~~~~~ + + Tests utilities jinja uses. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import gc +import unittest + +import pickle + +from jinja2.testsuite import JinjaTestCase + +from jinja2.utils import LRUCache, escape, object_type_repr + + +class LRUCacheTestCase(JinjaTestCase): + + def test_simple(self): + d = LRUCache(3) + d["a"] = 1 + d["b"] = 2 + d["c"] = 3 + d["a"] + d["d"] = 4 + assert len(d) == 3 + assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d + + def test_pickleable(self): + cache = LRUCache(2) + cache["foo"] = 42 + cache["bar"] = 23 + cache["foo"] + + for protocol in range(3): + copy = pickle.loads(pickle.dumps(cache, protocol)) + assert copy.capacity == cache.capacity + assert copy._mapping == cache._mapping + assert copy._queue == cache._queue + + +class HelpersTestCase(JinjaTestCase): + + def test_object_type_repr(self): + class X(object): + pass + self.assert_equal(object_type_repr(42), 'int object') + self.assert_equal(object_type_repr([]), 'list object') + self.assert_equal(object_type_repr(X()), + 'jinja2.testsuite.utils.X object') + self.assert_equal(object_type_repr(None), 'None') + self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis') + + +class MarkupLeakTestCase(JinjaTestCase): + + def test_markup_leaks(self): + counts = set() + for count in range(20): + for item in range(1000): + escape("foo") + escape("<foo>") + escape(u"foo") + escape(u"<foo>") + counts.add(len(gc.get_objects())) + assert len(counts) == 1, 'ouch, c extension seems to leak objects' + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(LRUCacheTestCase)) + suite.addTest(unittest.makeSuite(HelpersTestCase)) + + # this test only tests the c extension + if not hasattr(escape, 'func_code'): + suite.addTest(unittest.makeSuite(MarkupLeakTestCase)) + + return suite diff --git a/module/lib/jinja2/utils.py b/module/lib/jinja2/utils.py index 7b77b8eb7..ddc47da0a 100644 --- a/module/lib/jinja2/utils.py +++ b/module/lib/jinja2/utils.py @@ -9,21 +9,17 @@ :license: BSD, see LICENSE for more details. """ import re -import sys import errno -try: - from thread import allocate_lock -except ImportError: - from dummy_thread import allocate_lock from collections import deque -from itertools import imap +from jinja2._compat import text_type, string_types, implements_iterator, \ + allocate_lock, url_quote _word_split_re = re.compile(r'(\s+)') _punctuation_re = re.compile( '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % ( - '|'.join(imap(re.escape, ('(', '<', '<'))), - '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '>'))) + '|'.join(map(re.escape, ('(', '<', '<'))), + '|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '>'))) ) ) _simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$') @@ -38,77 +34,7 @@ missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})() # internal code internal_code = set() - -# concatenate a list of strings and convert them to unicode. -# unfortunately there is a bug in python 2.4 and lower that causes -# unicode.join trash the traceback. -_concat = u''.join -try: - def _test_gen_bug(): - raise TypeError(_test_gen_bug) - yield None - _concat(_test_gen_bug()) -except TypeError, _error: - if not _error.args or _error.args[0] is not _test_gen_bug: - def concat(gen): - try: - return _concat(list(gen)) - except: - # this hack is needed so that the current frame - # does not show up in the traceback. - exc_type, exc_value, tb = sys.exc_info() - raise exc_type, exc_value, tb.tb_next - else: - concat = _concat - del _test_gen_bug, _error - - -# for python 2.x we create outselves a next() function that does the -# basics without exception catching. -try: - next = next -except NameError: - def next(x): - return x.next() - - -# if this python version is unable to deal with unicode filenames -# when passed to encode we let this function encode it properly. -# This is used in a couple of places. As far as Jinja is concerned -# filenames are unicode *or* bytestrings in 2.x and unicode only in -# 3.x because compile cannot handle bytes -if sys.version_info < (3, 0): - def _encode_filename(filename): - if isinstance(filename, unicode): - return filename.encode('utf-8') - return filename -else: - def _encode_filename(filename): - assert filename is None or isinstance(filename, str), \ - 'filenames must be strings' - return filename - -from keyword import iskeyword as is_python_keyword - - -# common types. These do exist in the special types module too which however -# does not exist in IronPython out of the box. Also that way we don't have -# to deal with implementation specific stuff here -class _C(object): - def method(self): pass -def _func(): - yield None -FunctionType = type(_func) -GeneratorType = type(_func()) -MethodType = type(_C.method) -CodeType = type(_C.method.func_code) -try: - raise TypeError() -except TypeError: - _tb = sys.exc_info()[2] - TracebackType = type(_tb) - FrameType = type(_tb.tb_frame) -del _C, _tb, _func +concat = u''.join def contextfunction(f): @@ -128,7 +54,7 @@ def contextfunction(f): def evalcontextfunction(f): - """This decoraotr can be used to mark a function or method as an eval + """This decorator can be used to mark a function or method as an eval context callable. This is similar to the :func:`contextfunction` but instead of passing the context, an evaluation context object is passed. For more information about the eval context, see @@ -152,7 +78,7 @@ def environmentfunction(f): def internalcode(f): """Marks the function as internally used""" - internal_code.add(f.func_code) + internal_code.add(f.__code__) return f @@ -191,7 +117,7 @@ def clear_caches(): def import_string(import_name, silent=False): - """Imports an object based on a string. This use useful if you want to + """Imports an object based on a string. This is useful if you want to use import paths as endpoints or something similar. An import path can be specified either in dotted notation (``xml.sax.saxutils.escape``) or with a colon as object delimiter (``xml.sax.saxutils:escape``). @@ -222,7 +148,7 @@ def open_if_exists(filename, mode='rb'): """ try: return open(filename, mode) - except IOError, e: + except IOError as e: if e.errno not in (errno.ENOENT, errno.EISDIR): raise @@ -271,7 +197,7 @@ def urlize(text, trim_url_limit=None, nofollow=False): trim_url = lambda x, limit=trim_url_limit: limit is not None \ and (x[:limit] + (len(x) >=limit and '...' or '')) or x - words = _word_split_re.split(unicode(escape(text))) + words = _word_split_re.split(text_type(escape(text))) nofollow_attr = nofollow and ' rel="nofollow"' or '' for i, word in enumerate(words): match = _punctuation_re.match(word) @@ -280,6 +206,7 @@ def urlize(text, trim_url_limit=None, nofollow=False): if middle.startswith('www.') or ( '@' not in middle and not middle.startswith('http://') and + not middle.startswith('https://') and len(middle) > 0 and middle[0] in _letters + _digits and ( middle.endswith('.org') or @@ -307,7 +234,7 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100): words = LOREM_IPSUM_WORDS.split() result = [] - for _ in xrange(n): + for _ in range(n): next_capitalized = True last_comma = last_fullstop = 0 word = None @@ -315,7 +242,7 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100): p = [] # each paragraph contains out of 20 to 100 words. - for idx, _ in enumerate(xrange(randrange(min, max))): + for idx, _ in enumerate(range(randrange(min, max))): while True: word = choice(words) if word != last: @@ -349,6 +276,21 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100): return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result)) +def unicode_urlencode(obj, charset='utf-8'): + """URL escapes a single bytestring or unicode string with the + given charset if applicable to URL safe quoting under all rules + that need to be considered under all supported Python versions. + + If non strings are provided they are converted to their unicode + representation first. + """ + if not isinstance(obj, string_types): + obj = text_type(obj) + if isinstance(obj, text_type): + obj = obj.encode(charset) + return text_type(url_quote(obj)) + + class LRUCache(object): """A simple LRU Cache implementation.""" @@ -366,18 +308,10 @@ class LRUCache(object): # alias all queue methods for faster lookup self._popleft = self._queue.popleft self._pop = self._queue.pop - if hasattr(self._queue, 'remove'): - self._remove = self._queue.remove + self._remove = self._queue.remove self._wlock = allocate_lock() self._append = self._queue.append - def _remove(self, obj): - """Python 2.4 compatibility.""" - for idx, item in enumerate(self._queue): - if item == obj: - del self._queue[idx] - break - def __getstate__(self): return { 'capacity': self.capacity, @@ -393,7 +327,7 @@ class LRUCache(object): return (self.capacity,) def copy(self): - """Return an shallow copy of the instance.""" + """Return a shallow copy of the instance.""" rv = self.__class__(self.capacity) rv._mapping.update(self._mapping) rv._queue = deque(self._queue) @@ -410,11 +344,15 @@ class LRUCache(object): """Set `default` if the key is not in the cache otherwise leave unchanged. Return the value of this key. """ + self._wlock.acquire() try: - return self[key] - except KeyError: - self[key] = default - return default + try: + return self[key] + except KeyError: + self[key] = default + return default + finally: + self._wlock.release() def clear(self): """Clear the cache.""" @@ -443,19 +381,23 @@ class LRUCache(object): """Get an item from the cache. Moves the item up so that it has the highest priority then. - Raise an `KeyError` if it does not exist. + Raise a `KeyError` if it does not exist. """ - rv = self._mapping[key] - if self._queue[-1] != key: - try: - self._remove(key) - except ValueError: - # if something removed the key from the container - # when we read, ignore the ValueError that we would - # get otherwise. - pass - self._append(key) - return rv + self._wlock.acquire() + try: + rv = self._mapping[key] + if self._queue[-1] != key: + try: + self._remove(key) + except ValueError: + # if something removed the key from the container + # when we read, ignore the ValueError that we would + # get otherwise. + pass + self._append(key) + return rv + finally: + self._wlock.release() def __setitem__(self, key, value): """Sets the value for an item. Moves the item up so that it @@ -464,11 +406,7 @@ class LRUCache(object): self._wlock.acquire() try: if key in self._mapping: - try: - self._remove(key) - except ValueError: - # __getitem__ is not locked, it might happen - pass + self._remove(key) elif len(self._mapping) == self.capacity: del self._mapping[self._popleft()] self._append(key) @@ -478,7 +416,7 @@ class LRUCache(object): def __delitem__(self, key): """Remove an item from the cache dict. - Raise an `KeyError` if it does not exist. + Raise a `KeyError` if it does not exist. """ self._wlock.acquire() try: @@ -538,6 +476,7 @@ except ImportError: pass +@implements_iterator class Cycler(object): """A cycle helper for templates.""" @@ -556,7 +495,7 @@ class Cycler(object): """Returns the current item.""" return self.items[self.pos] - def next(self): + def __next__(self): """Goes one item ahead and returns it.""" rv = self.current self.pos = (self.pos + 1) % len(self.items) @@ -577,25 +516,5 @@ class Joiner(object): return self.sep -# try markupsafe first, if that fails go with Jinja2's bundled version -# of markupsafe. Markupsafe was previously Jinja2's implementation of -# the Markup object but was moved into a separate package in a patchleve -# release -try: - from markupsafe import Markup, escape, soft_unicode -except ImportError: - from jinja2._markupsafe import Markup, escape, soft_unicode - - -# partials -try: - from functools import partial -except ImportError: - class partial(object): - def __init__(self, _func, *args, **kwargs): - self._func = _func - self._args = args - self._kwargs = kwargs - def __call__(self, *args, **kwargs): - kwargs.update(self._kwargs) - return self._func(*(self._args + args), **kwargs) +# Imported here because that's where it was in the past +from markupsafe import Markup, escape, soft_unicode diff --git a/module/lib/jinja2/_markupsafe/__init__.py b/module/lib/markupsafe/__init__.py index ec7bd572d..275540154 100644 --- a/module/lib/jinja2/_markupsafe/__init__.py +++ b/module/lib/markupsafe/__init__.py @@ -9,7 +9,10 @@ :license: BSD, see LICENSE for more details. """ import re -from itertools import imap +import string +from collections import Mapping +from markupsafe._compat import text_type, string_types, int_types, \ + unichr, iteritems, PY2 __all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent'] @@ -19,7 +22,7 @@ _striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)') _entity_re = re.compile(r'&([^;]+);') -class Markup(unicode): +class Markup(text_type): r"""Marks a string as being safe for inclusion in HTML/XML output without needing to be escaped. This implements the `__html__` interface a couple of frameworks and web applications use. :class:`Markup` is a direct @@ -40,7 +43,7 @@ class Markup(unicode): >>> class Foo(object): ... def __html__(self): ... return '<a href="#">foo</a>' - ... + ... >>> Markup(Foo()) Markup(u'<a href="#">foo</a>') @@ -68,65 +71,66 @@ class Markup(unicode): if hasattr(base, '__html__'): base = base.__html__() if encoding is None: - return unicode.__new__(cls, base) - return unicode.__new__(cls, base, encoding, errors) + return text_type.__new__(cls, base) + return text_type.__new__(cls, base, encoding, errors) def __html__(self): return self def __add__(self, other): - if hasattr(other, '__html__') or isinstance(other, basestring): - return self.__class__(unicode(self) + unicode(escape(other))) + if isinstance(other, string_types) or hasattr(other, '__html__'): + return self.__class__(super(Markup, self).__add__(self.escape(other))) return NotImplemented def __radd__(self, other): - if hasattr(other, '__html__') or isinstance(other, basestring): - return self.__class__(unicode(escape(other)) + unicode(self)) + if hasattr(other, '__html__') or isinstance(other, string_types): + return self.escape(other).__add__(self) return NotImplemented def __mul__(self, num): - if isinstance(num, (int, long)): - return self.__class__(unicode.__mul__(self, num)) + if isinstance(num, int_types): + return self.__class__(text_type.__mul__(self, num)) return NotImplemented __rmul__ = __mul__ def __mod__(self, arg): if isinstance(arg, tuple): - arg = tuple(imap(_MarkupEscapeHelper, arg)) + arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg) else: - arg = _MarkupEscapeHelper(arg) - return self.__class__(unicode.__mod__(self, arg)) + arg = _MarkupEscapeHelper(arg, self.escape) + return self.__class__(text_type.__mod__(self, arg)) def __repr__(self): return '%s(%s)' % ( self.__class__.__name__, - unicode.__repr__(self) + text_type.__repr__(self) ) def join(self, seq): - return self.__class__(unicode.join(self, imap(escape, seq))) - join.__doc__ = unicode.join.__doc__ + return self.__class__(text_type.join(self, map(self.escape, seq))) + join.__doc__ = text_type.join.__doc__ def split(self, *args, **kwargs): - return map(self.__class__, unicode.split(self, *args, **kwargs)) - split.__doc__ = unicode.split.__doc__ + return list(map(self.__class__, text_type.split(self, *args, **kwargs))) + split.__doc__ = text_type.split.__doc__ def rsplit(self, *args, **kwargs): - return map(self.__class__, unicode.rsplit(self, *args, **kwargs)) - rsplit.__doc__ = unicode.rsplit.__doc__ + return list(map(self.__class__, text_type.rsplit(self, *args, **kwargs))) + rsplit.__doc__ = text_type.rsplit.__doc__ def splitlines(self, *args, **kwargs): - return map(self.__class__, unicode.splitlines(self, *args, **kwargs)) - splitlines.__doc__ = unicode.splitlines.__doc__ + return list(map(self.__class__, text_type.splitlines( + self, *args, **kwargs))) + splitlines.__doc__ = text_type.splitlines.__doc__ def unescape(self): - r"""Unescape markup again into an unicode string. This also resolves + r"""Unescape markup again into an text_type string. This also resolves known HTML4 and XHTML entities: >>> Markup("Main » <em>About</em>").unescape() u'Main \xbb <em>About</em>' """ - from jinja2._markupsafe._constants import HTML_ENTITIES + from markupsafe._constants import HTML_ENTITIES def handle_match(m): name = m.group(1) if name in HTML_ENTITIES: @@ -139,10 +143,10 @@ class Markup(unicode): except ValueError: pass return u'' - return _entity_re.sub(handle_match, unicode(self)) + return _entity_re.sub(handle_match, text_type(self)) def striptags(self): - r"""Unescape markup into an unicode string and strip all tags. This + r"""Unescape markup into an text_type string and strip all tags. This also resolves known HTML4 and XHTML entities. Whitespace is normalized to one: @@ -163,11 +167,11 @@ class Markup(unicode): return cls(rv) return rv - def make_wrapper(name): - orig = getattr(unicode, name) + def make_simple_escaping_wrapper(name): + orig = getattr(text_type, name) def func(self, *args, **kwargs): - args = _escape_argspec(list(args), enumerate(args)) - _escape_argspec(kwargs, kwargs.iteritems()) + args = _escape_argspec(list(args), enumerate(args), self.escape) + _escape_argspec(kwargs, iteritems(kwargs), self.escape) return self.__class__(orig(self, *args, **kwargs)) func.__name__ = orig.__name__ func.__doc__ = orig.__doc__ @@ -177,28 +181,93 @@ class Markup(unicode): 'title', 'lower', 'upper', 'replace', 'ljust', \ 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \ 'translate', 'expandtabs', 'swapcase', 'zfill': - locals()[method] = make_wrapper(method) + locals()[method] = make_simple_escaping_wrapper(method) # new in python 2.5 - if hasattr(unicode, 'partition'): - partition = make_wrapper('partition'), - rpartition = make_wrapper('rpartition') + if hasattr(text_type, 'partition'): + def partition(self, sep): + return tuple(map(self.__class__, + text_type.partition(self, self.escape(sep)))) + def rpartition(self, sep): + return tuple(map(self.__class__, + text_type.rpartition(self, self.escape(sep)))) # new in python 2.6 - if hasattr(unicode, 'format'): - format = make_wrapper('format') + if hasattr(text_type, 'format'): + def format(*args, **kwargs): + self, args = args[0], args[1:] + formatter = EscapeFormatter(self.escape) + kwargs = _MagicFormatMapping(args, kwargs) + return self.__class__(formatter.vformat(self, args, kwargs)) + + def __html_format__(self, format_spec): + if format_spec: + raise ValueError('Unsupported format specification ' + 'for Markup.') + return self # not in python 3 - if hasattr(unicode, '__getslice__'): - __getslice__ = make_wrapper('__getslice__') + if hasattr(text_type, '__getslice__'): + __getslice__ = make_simple_escaping_wrapper('__getslice__') - del method, make_wrapper + del method, make_simple_escaping_wrapper -def _escape_argspec(obj, iterable): +class _MagicFormatMapping(Mapping): + """This class implements a dummy wrapper to fix a bug in the Python + standard library for string formatting. + + See http://bugs.python.org/issue13598 for information about why + this is necessary. + """ + + def __init__(self, args, kwargs): + self._args = args + self._kwargs = kwargs + self._last_index = 0 + + def __getitem__(self, key): + if key == '': + idx = self._last_index + self._last_index += 1 + try: + return self._args[idx] + except LookupError: + pass + key = str(idx) + return self._kwargs[key] + + def __iter__(self): + return iter(self._kwargs) + + def __len__(self): + return len(self._kwargs) + + +if hasattr(text_type, 'format'): + class EscapeFormatter(string.Formatter): + + def __init__(self, escape): + self.escape = escape + + def format_field(self, value, format_spec): + if hasattr(value, '__html_format__'): + rv = value.__html_format__(format_spec) + elif hasattr(value, '__html__'): + if format_spec: + raise ValueError('No format specification allowed ' + 'when formatting an object with ' + 'its __html__ method.') + rv = value.__html__() + else: + rv = string.Formatter.format_field(self, value, format_spec) + return text_type(self.escape(rv)) + + +def _escape_argspec(obj, iterable, escape): """Helper for various string-wrapped functions.""" for key, value in iterable: - if hasattr(value, '__html__') or isinstance(value, basestring): + if hasattr(value, '__html__') or isinstance(value, string_types): obj[key] = escape(value) return obj @@ -206,13 +275,13 @@ def _escape_argspec(obj, iterable): class _MarkupEscapeHelper(object): """Helper for Markup.__mod__""" - def __init__(self, obj): + def __init__(self, obj, escape): self.obj = obj + self.escape = escape - __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x]) - __str__ = lambda s: str(escape(s.obj)) - __unicode__ = lambda s: unicode(escape(s.obj)) - __repr__ = lambda s: str(escape(repr(s.obj))) + __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x], s.escape) + __unicode__ = __str__ = lambda s: text_type(s.escape(s.obj)) + __repr__ = lambda s: str(s.escape(repr(s.obj))) __int__ = lambda s: int(s.obj) __float__ = lambda s: float(s.obj) @@ -220,6 +289,10 @@ class _MarkupEscapeHelper(object): # we have to import it down here as the speedups and native # modules imports the markup type which is define above. try: - from jinja2._markupsafe._speedups import escape, escape_silent, soft_unicode + from markupsafe._speedups import escape, escape_silent, soft_unicode except ImportError: - from jinja2._markupsafe._native import escape, escape_silent, soft_unicode + from markupsafe._native import escape, escape_silent, soft_unicode + +if not PY2: + soft_str = soft_unicode + __all__.append('soft_str') diff --git a/module/lib/markupsafe/_compat.py b/module/lib/markupsafe/_compat.py new file mode 100644 index 000000000..62e5632ad --- /dev/null +++ b/module/lib/markupsafe/_compat.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +""" + markupsafe._compat + ~~~~~~~~~~~~~~~~~~ + + Compatibility module for different Python versions. + + :copyright: (c) 2013 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import sys + +PY2 = sys.version_info[0] == 2 + +if not PY2: + text_type = str + string_types = (str,) + unichr = chr + int_types = (int,) + iteritems = lambda x: iter(x.items()) +else: + text_type = unicode + string_types = (str, unicode) + unichr = unichr + int_types = (int, long) + iteritems = lambda x: x.iteritems() diff --git a/module/lib/jinja2/_markupsafe/_constants.py b/module/lib/markupsafe/_constants.py index 919bf03c5..919bf03c5 100644 --- a/module/lib/jinja2/_markupsafe/_constants.py +++ b/module/lib/markupsafe/_constants.py diff --git a/module/lib/jinja2/_markupsafe/_native.py b/module/lib/markupsafe/_native.py index 7b95828ec..5e83f10a1 100644 --- a/module/lib/jinja2/_markupsafe/_native.py +++ b/module/lib/markupsafe/_native.py @@ -8,7 +8,8 @@ :copyright: (c) 2010 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from jinja2._markupsafe import Markup +from markupsafe import Markup +from markupsafe._compat import text_type def escape(s): @@ -18,7 +19,7 @@ def escape(s): """ if hasattr(s, '__html__'): return s.__html__() - return Markup(unicode(s) + return Markup(text_type(s) .replace('&', '&') .replace('>', '>') .replace('<', '<') @@ -40,6 +41,6 @@ def soft_unicode(s): """Make a string unicode if it isn't already. That way a markup string is not converted back to unicode. """ - if not isinstance(s, unicode): - s = unicode(s) + if not isinstance(s, text_type): + s = text_type(s) return s diff --git a/module/lib/markupsafe/_speedups.c b/module/lib/markupsafe/_speedups.c new file mode 100644 index 000000000..f349febf2 --- /dev/null +++ b/module/lib/markupsafe/_speedups.c @@ -0,0 +1,239 @@ +/** + * markupsafe._speedups + * ~~~~~~~~~~~~~~~~~~~~ + * + * This module implements functions for automatic escaping in C for better + * performance. + * + * :copyright: (c) 2010 by Armin Ronacher. + * :license: BSD. + */ + +#include <Python.h> + +#define ESCAPED_CHARS_TABLE_SIZE 63 +#define UNICHR(x) (PyUnicode_AS_UNICODE((PyUnicodeObject*)PyUnicode_DecodeASCII(x, strlen(x), NULL))); + +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + + +static PyObject* markup; +static Py_ssize_t escaped_chars_delta_len[ESCAPED_CHARS_TABLE_SIZE]; +static Py_UNICODE *escaped_chars_repl[ESCAPED_CHARS_TABLE_SIZE]; + +static int +init_constants(void) +{ + PyObject *module; + /* happing of characters to replace */ + escaped_chars_repl['"'] = UNICHR("""); + escaped_chars_repl['\''] = UNICHR("'"); + escaped_chars_repl['&'] = UNICHR("&"); + escaped_chars_repl['<'] = UNICHR("<"); + escaped_chars_repl['>'] = UNICHR(">"); + + /* lengths of those characters when replaced - 1 */ + memset(escaped_chars_delta_len, 0, sizeof (escaped_chars_delta_len)); + escaped_chars_delta_len['"'] = escaped_chars_delta_len['\''] = \ + escaped_chars_delta_len['&'] = 4; + escaped_chars_delta_len['<'] = escaped_chars_delta_len['>'] = 3; + + /* import markup type so that we can mark the return value */ + module = PyImport_ImportModule("markupsafe"); + if (!module) + return 0; + markup = PyObject_GetAttrString(module, "Markup"); + Py_DECREF(module); + + return 1; +} + +static PyObject* +escape_unicode(PyUnicodeObject *in) +{ + PyUnicodeObject *out; + Py_UNICODE *inp = PyUnicode_AS_UNICODE(in); + const Py_UNICODE *inp_end = PyUnicode_AS_UNICODE(in) + PyUnicode_GET_SIZE(in); + Py_UNICODE *next_escp; + Py_UNICODE *outp; + Py_ssize_t delta=0, erepl=0, delta_len=0; + + /* First we need to figure out how long the escaped string will be */ + while (*(inp) || inp < inp_end) { + if (*inp < ESCAPED_CHARS_TABLE_SIZE) { + delta += escaped_chars_delta_len[*inp]; + erepl += !!escaped_chars_delta_len[*inp]; + } + ++inp; + } + + /* Do we need to escape anything at all? */ + if (!erepl) { + Py_INCREF(in); + return (PyObject*)in; + } + + out = (PyUnicodeObject*)PyUnicode_FromUnicode(NULL, PyUnicode_GET_SIZE(in) + delta); + if (!out) + return NULL; + + outp = PyUnicode_AS_UNICODE(out); + inp = PyUnicode_AS_UNICODE(in); + while (erepl-- > 0) { + /* look for the next substitution */ + next_escp = inp; + while (next_escp < inp_end) { + if (*next_escp < ESCAPED_CHARS_TABLE_SIZE && + (delta_len = escaped_chars_delta_len[*next_escp])) { + ++delta_len; + break; + } + ++next_escp; + } + + if (next_escp > inp) { + /* copy unescaped chars between inp and next_escp */ + Py_UNICODE_COPY(outp, inp, next_escp-inp); + outp += next_escp - inp; + } + + /* escape 'next_escp' */ + Py_UNICODE_COPY(outp, escaped_chars_repl[*next_escp], delta_len); + outp += delta_len; + + inp = next_escp + 1; + } + if (inp < inp_end) + Py_UNICODE_COPY(outp, inp, PyUnicode_GET_SIZE(in) - (inp - PyUnicode_AS_UNICODE(in))); + + return (PyObject*)out; +} + + +static PyObject* +escape(PyObject *self, PyObject *text) +{ + PyObject *s = NULL, *rv = NULL, *html; + + /* we don't have to escape integers, bools or floats */ + if (PyLong_CheckExact(text) || +#if PY_MAJOR_VERSION < 3 + PyInt_CheckExact(text) || +#endif + PyFloat_CheckExact(text) || PyBool_Check(text) || + text == Py_None) + return PyObject_CallFunctionObjArgs(markup, text, NULL); + + /* if the object has an __html__ method that performs the escaping */ + html = PyObject_GetAttrString(text, "__html__"); + if (html) { + rv = PyObject_CallObject(html, NULL); + Py_DECREF(html); + return rv; + } + + /* otherwise make the object unicode if it isn't, then escape */ + PyErr_Clear(); + if (!PyUnicode_Check(text)) { +#if PY_MAJOR_VERSION < 3 + PyObject *unicode = PyObject_Unicode(text); +#else + PyObject *unicode = PyObject_Str(text); +#endif + if (!unicode) + return NULL; + s = escape_unicode((PyUnicodeObject*)unicode); + Py_DECREF(unicode); + } + else + s = escape_unicode((PyUnicodeObject*)text); + + /* convert the unicode string into a markup object. */ + rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL); + Py_DECREF(s); + return rv; +} + + +static PyObject* +escape_silent(PyObject *self, PyObject *text) +{ + if (text != Py_None) + return escape(self, text); + return PyObject_CallFunctionObjArgs(markup, NULL); +} + + +static PyObject* +soft_unicode(PyObject *self, PyObject *s) +{ + if (!PyUnicode_Check(s)) +#if PY_MAJOR_VERSION < 3 + return PyObject_Unicode(s); +#else + return PyObject_Str(s); +#endif + Py_INCREF(s); + return s; +} + + +static PyMethodDef module_methods[] = { + {"escape", (PyCFunction)escape, METH_O, + "escape(s) -> markup\n\n" + "Convert the characters &, <, >, ', and \" in string s to HTML-safe\n" + "sequences. Use this if you need to display text that might contain\n" + "such characters in HTML. Marks return value as markup string."}, + {"escape_silent", (PyCFunction)escape_silent, METH_O, + "escape_silent(s) -> markup\n\n" + "Like escape but converts None to an empty string."}, + {"soft_unicode", (PyCFunction)soft_unicode, METH_O, + "soft_unicode(object) -> string\n\n" + "Make a string unicode if it isn't already. That way a markup\n" + "string is not converted back to unicode."}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + + +#if PY_MAJOR_VERSION < 3 + +#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ +#define PyMODINIT_FUNC void +#endif +PyMODINIT_FUNC +init_speedups(void) +{ + if (!init_constants()) + return; + + Py_InitModule3("markupsafe._speedups", module_methods, ""); +} + +#else /* Python 3.x module initialization */ + +static struct PyModuleDef module_definition = { + PyModuleDef_HEAD_INIT, + "markupsafe._speedups", + NULL, + -1, + module_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__speedups(void) +{ + if (!init_constants()) + return NULL; + + return PyModule_Create(&module_definition); +} + +#endif diff --git a/module/lib/markupsafe/tests.py b/module/lib/markupsafe/tests.py new file mode 100644 index 000000000..636993629 --- /dev/null +++ b/module/lib/markupsafe/tests.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +import gc +import sys +import unittest +from markupsafe import Markup, escape, escape_silent +from markupsafe._compat import text_type + + +class MarkupTestCase(unittest.TestCase): + + def test_adding(self): + # adding two strings should escape the unsafe one + unsafe = '<script type="application/x-some-script">alert("foo");</script>' + safe = Markup('<em>username</em>') + assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe) + + def test_string_interpolation(self): + # string interpolations are safe to use too + assert Markup('<em>%s</em>') % '<bad user>' == \ + '<em><bad user></em>' + assert Markup('<em>%(username)s</em>') % { + 'username': '<bad user>' + } == '<em><bad user></em>' + + assert Markup('%i') % 3.14 == '3' + assert Markup('%.2f') % 3.14 == '3.14' + + def test_type_behavior(self): + # an escaped object is markup too + assert type(Markup('foo') + 'bar') is Markup + + # and it implements __html__ by returning itself + x = Markup("foo") + assert x.__html__() is x + + def test_html_interop(self): + # it also knows how to treat __html__ objects + class Foo(object): + def __html__(self): + return '<em>awesome</em>' + def __unicode__(self): + return 'awesome' + __str__ = __unicode__ + assert Markup(Foo()) == '<em>awesome</em>' + assert Markup('<strong>%s</strong>') % Foo() == \ + '<strong><em>awesome</em></strong>' + + def test_tuple_interpol(self): + self.assertEqual(Markup('<em>%s:%s</em>') % ( + '<foo>', + '<bar>', + ), Markup(u'<em><foo>:<bar></em>')) + + def test_dict_interpol(self): + self.assertEqual(Markup('<em>%(foo)s</em>') % { + 'foo': '<foo>', + }, Markup(u'<em><foo></em>')) + self.assertEqual(Markup('<em>%(foo)s:%(bar)s</em>') % { + 'foo': '<foo>', + 'bar': '<bar>', + }, Markup(u'<em><foo>:<bar></em>')) + + def test_escaping(self): + # escaping and unescaping + assert escape('"<>&\'') == '"<>&'' + assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar" + assert Markup("<test>").unescape() == "<test>" + + def test_formatting(self): + for actual, expected in ( + (Markup('%i') % 3.14, '3'), + (Markup('%.2f') % 3.14159, '3.14'), + (Markup('%s %s %s') % ('<', 123, '>'), '< 123 >'), + (Markup('<em>{awesome}</em>').format(awesome='<awesome>'), + '<em><awesome></em>'), + (Markup('{0[1][bar]}').format([0, {'bar': '<bar/>'}]), + '<bar/>'), + (Markup('{0[1][bar]}').format([0, {'bar': Markup('<bar/>')}]), + '<bar/>')): + assert actual == expected, "%r should be %r!" % (actual, expected) + + # This is new in 2.7 + if sys.version_info >= (2, 7): + def test_formatting_empty(self): + formatted = Markup('{}').format(0) + assert formatted == Markup('0') + + def test_custom_formatting(self): + class HasHTMLOnly(object): + def __html__(self): + return Markup('<foo>') + + class HasHTMLAndFormat(object): + def __html__(self): + return Markup('<foo>') + def __html_format__(self, spec): + return Markup('<FORMAT>') + + assert Markup('{0}').format(HasHTMLOnly()) == Markup('<foo>') + assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('<FORMAT>') + + def test_complex_custom_formatting(self): + class User(object): + def __init__(self, id, username): + self.id = id + self.username = username + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('<a href="/user/{0}">{1}</a>').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + def __html__(self): + return Markup('<span class=user>{0}</span>').format(self.username) + + user = User(1, 'foo') + assert Markup('<p>User: {0:link}').format(user) == \ + Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>') + + def test_all_set(self): + import markupsafe as markup + for item in markup.__all__: + getattr(markup, item) + + def test_escape_silent(self): + assert escape_silent(None) == Markup() + assert escape(None) == Markup(None) + assert escape_silent('<foo>') == Markup(u'<foo>') + + def test_splitting(self): + self.assertEqual(Markup('a b').split(), [ + Markup('a'), + Markup('b') + ]) + self.assertEqual(Markup('a b').rsplit(), [ + Markup('a'), + Markup('b') + ]) + self.assertEqual(Markup('a\nb').splitlines(), [ + Markup('a'), + Markup('b') + ]) + + def test_mul(self): + self.assertEqual(Markup('a') * 3, Markup('aaa')) + + +class MarkupLeakTestCase(unittest.TestCase): + + def test_markup_leaks(self): + counts = set() + for count in range(20): + for item in range(1000): + escape("foo") + escape("<foo>") + escape(u"foo") + escape(u"<foo>") + counts.add(len(gc.get_objects())) + assert len(counts) == 1, 'ouch, c extension seems to leak objects' + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(MarkupTestCase)) + + # this test only tests the c extension + if not hasattr(escape, 'func_code'): + suite.addTest(unittest.makeSuite(MarkupLeakTestCase)) + + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') + +# vim:sts=4:sw=4:et: diff --git a/module/lib/simplejson/__init__.py b/module/lib/simplejson/__init__.py index ef5c0db48..a5c01379a 100644 --- a/module/lib/simplejson/__init__.py +++ b/module/lib/simplejson/__init__.py @@ -14,15 +14,15 @@ Encoding basic Python object hierarchies:: >>> import simplejson as json >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) '["foo", {"bar": ["baz", null, 1.0, 2]}]' - >>> print json.dumps("\"foo\bar") + >>> print(json.dumps("\"foo\bar")) "\"foo\bar" - >>> print json.dumps(u'\u1234') + >>> print(json.dumps(u'\u1234')) "\u1234" - >>> print json.dumps('\\') + >>> print(json.dumps('\\')) "\\" - >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True) + >>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)) {"a": 0, "b": 0, "c": 0} - >>> from StringIO import StringIO + >>> from simplejson.compat import StringIO >>> io = StringIO() >>> json.dump(['streaming API'], io) >>> io.getvalue() @@ -31,14 +31,14 @@ Encoding basic Python object hierarchies:: Compact encoding:: >>> import simplejson as json - >>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':')) + >>> obj = [1,2,3,{'4': 5, '6': 7}] + >>> json.dumps(obj, separators=(',',':'), sort_keys=True) '[1,2,3,{"4":5,"6":7}]' Pretty printing:: >>> import simplejson as json - >>> s = json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=' ') - >>> print '\n'.join([l.rstrip() for l in s.splitlines()]) + >>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=' ')) { "4": 5, "6": 7 @@ -52,7 +52,7 @@ Decoding JSON:: True >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar' True - >>> from StringIO import StringIO + >>> from simplejson.compat import StringIO >>> io = StringIO('["streaming API"]') >>> json.load(io)[0] == 'streaming API' True @@ -95,33 +95,35 @@ Using simplejson.tool from the shell to validate and pretty-print:: "json": "obj" } $ echo '{ 1.2:3.4}' | python -m simplejson.tool - Expecting property name: line 1 column 2 (char 2) + Expecting property name: line 1 column 3 (char 2) """ -__version__ = '2.2.1' +from __future__ import absolute_import +__version__ = '3.5.3' __all__ = [ 'dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', - 'OrderedDict', + 'OrderedDict', 'simple_first', ] __author__ = 'Bob Ippolito <bob@redivi.com>' from decimal import Decimal -from decoder import JSONDecoder, JSONDecodeError -from encoder import JSONEncoder +from .scanner import JSONDecodeError +from .decoder import JSONDecoder +from .encoder import JSONEncoder, JSONEncoderForHTML def _import_OrderedDict(): import collections try: return collections.OrderedDict except AttributeError: - import ordered_dict + from . import ordered_dict return ordered_dict.OrderedDict OrderedDict = _import_OrderedDict() def _import_c_make_encoder(): try: - from simplejson._speedups import make_encoder + from ._speedups import make_encoder return make_encoder except ImportError: return None @@ -138,34 +140,41 @@ _default_encoder = JSONEncoder( use_decimal=True, namedtuple_as_object=True, tuple_as_array=True, + bigint_as_string=False, + item_sort_key=None, + for_json=False, + ignore_nan=False, + int_as_string_bitcount=None, ) def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, - allow_nan=True, cls=None, indent=None, separators=None, - encoding='utf-8', default=None, use_decimal=True, - namedtuple_as_object=True, tuple_as_array=True, - **kw): + allow_nan=True, cls=None, indent=None, separators=None, + encoding='utf-8', default=None, use_decimal=True, + namedtuple_as_object=True, tuple_as_array=True, + bigint_as_string=False, sort_keys=False, item_sort_key=None, + for_json=False, ignore_nan=False, int_as_string_bitcount=None, **kw): """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a ``.write()``-supporting file-like object). - If ``skipkeys`` is true then ``dict`` keys that are not basic types + If *skipkeys* is true then ``dict`` keys that are not basic types (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. - If ``ensure_ascii`` is false, then the some chunks written to ``fp`` + If *ensure_ascii* is false, then the some chunks written to ``fp`` may be ``unicode`` instances, subject to normal Python ``str`` to ``unicode`` coercion rules. Unless ``fp.write()`` explicitly understands ``unicode`` (as in ``codecs.getwriter()``) this is likely to cause an error. - If ``check_circular`` is false, then the circular reference check + If *check_circular* is false, then the circular reference check for container types will be skipped and a circular reference will result in an ``OverflowError`` (or worse). - If ``allow_nan`` is false, then it will be a ``ValueError`` to + If *allow_nan* is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) - in strict compliance of the JSON specification, instead of using the - JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). + in strict compliance of the original JSON specification, instead of using + the JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). See + *ignore_nan* for ECMA-262 compliant behavior. If *indent* is a string, then JSON array elements and object members will be pretty-printed with a newline followed by that string repeated @@ -174,14 +183,16 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, versions of simplejson earlier than 2.1.0, an integer is also accepted and is converted to a string with that many spaces. - If ``separators`` is an ``(item_separator, dict_separator)`` tuple - then it will be used instead of the default ``(', ', ': ')`` separators. - ``(',', ':')`` is the most compact JSON representation. + If specified, *separators* should be an + ``(item_separator, key_separator)`` tuple. The default is ``(', ', ': ')`` + if *indent* is ``None`` and ``(',', ': ')`` otherwise. To get the most + compact JSON representation, you should specify ``(',', ':')`` to eliminate + whitespace. - ``encoding`` is the character encoding for str instances, default is UTF-8. + *encoding* is the character encoding for str instances, default is UTF-8. - ``default(obj)`` is a function that should return a serializable version - of obj or raise TypeError. The default simply raises TypeError. + *default(obj)* is a function that should return a serializable version + of obj or raise ``TypeError``. The default simply raises ``TypeError``. If *use_decimal* is true (default: ``True``) then decimal.Decimal will be natively serialized to JSON with full precision. @@ -189,13 +200,41 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, If *namedtuple_as_object* is true (default: ``True``), :class:`tuple` subclasses with ``_asdict()`` methods will be encoded as JSON objects. - + If *tuple_as_array* is true (default: ``True``), :class:`tuple` (and subclasses) will be encoded as JSON arrays. + If *bigint_as_string* is true (default: ``False``), ints 2**53 and higher + or lower than -2**53 will be encoded as strings. This is to avoid the + rounding that happens in Javascript otherwise. Note that this is still a + lossy operation that will not round-trip correctly and should be used + sparingly. + + If *int_as_string_bitcount* is a positive number (n), then int of size + greater than or equal to 2**n or lower than or equal to -2**n will be + encoded as strings. + + If specified, *item_sort_key* is a callable used to sort the items in + each dictionary. This is useful if you want to sort items other than + in alphabetical order by key. This option takes precedence over + *sort_keys*. + + If *sort_keys* is true (default: ``False``), the output of dictionaries + will be sorted by item. + + If *for_json* is true (default: ``False``), objects with a ``for_json()`` + method will use the return value of that method for encoding as JSON + instead of the object. + + If *ignore_nan* is true (default: ``False``), then out of range + :class:`float` values (``nan``, ``inf``, ``-inf``) will be serialized as + ``null`` in compliance with the ECMA-262 specification. If true, this will + override *allow_nan*. + To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the ``.default()`` method to serialize additional types), specify it with - the ``cls`` kwarg. + the ``cls`` kwarg. NOTE: You should use *default* or *for_json* instead + of subclassing whenever possible. """ # cached encoder @@ -203,7 +242,9 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, check_circular and allow_nan and cls is None and indent is None and separators is None and encoding == 'utf-8' and default is None and use_decimal - and namedtuple_as_object and tuple_as_array and not kw): + and namedtuple_as_object and tuple_as_array + and not bigint_as_string and int_as_string_bitcount is None + and not item_sort_key and not for_json and not ignore_nan and not kw): iterable = _default_encoder.iterencode(obj) else: if cls is None: @@ -214,6 +255,12 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, default=default, use_decimal=use_decimal, namedtuple_as_object=namedtuple_as_object, tuple_as_array=tuple_as_array, + bigint_as_string=bigint_as_string, + sort_keys=sort_keys, + item_sort_key=item_sort_key, + for_json=for_json, + ignore_nan=ignore_nan, + int_as_string_bitcount=int_as_string_bitcount, **kw).iterencode(obj) # could accelerate with writelines in some versions of Python, at # a debuggability cost @@ -222,11 +269,11 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, - allow_nan=True, cls=None, indent=None, separators=None, - encoding='utf-8', default=None, use_decimal=True, - namedtuple_as_object=True, - tuple_as_array=True, - **kw): + allow_nan=True, cls=None, indent=None, separators=None, + encoding='utf-8', default=None, use_decimal=True, + namedtuple_as_object=True, tuple_as_array=True, + bigint_as_string=False, sort_keys=False, item_sort_key=None, + for_json=False, ignore_nan=False, int_as_string_bitcount=None, **kw): """Serialize ``obj`` to a JSON formatted ``str``. If ``skipkeys`` is false then ``dict`` keys that are not basic types @@ -253,9 +300,11 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, versions of simplejson earlier than 2.1.0, an integer is also accepted and is converted to a string with that many spaces. - If ``separators`` is an ``(item_separator, dict_separator)`` tuple - then it will be used instead of the default ``(', ', ': ')`` separators. - ``(',', ':')`` is the most compact JSON representation. + If specified, ``separators`` should be an + ``(item_separator, key_separator)`` tuple. The default is ``(', ', ': ')`` + if *indent* is ``None`` and ``(',', ': ')`` otherwise. To get the most + compact JSON representation, you should specify ``(',', ':')`` to eliminate + whitespace. ``encoding`` is the character encoding for str instances, default is UTF-8. @@ -268,21 +317,52 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, If *namedtuple_as_object* is true (default: ``True``), :class:`tuple` subclasses with ``_asdict()`` methods will be encoded as JSON objects. - + If *tuple_as_array* is true (default: ``True``), :class:`tuple` (and subclasses) will be encoded as JSON arrays. + If *bigint_as_string* is true (not the default), ints 2**53 and higher + or lower than -2**53 will be encoded as strings. This is to avoid the + rounding that happens in Javascript otherwise. + + If *int_as_string_bitcount* is a positive number (n), then int of size + greater than or equal to 2**n or lower than or equal to -2**n will be + encoded as strings. + + If specified, *item_sort_key* is a callable used to sort the items in + each dictionary. This is useful if you want to sort items other than + in alphabetical order by key. This option takes precendence over + *sort_keys*. + + If *sort_keys* is true (default: ``False``), the output of dictionaries + will be sorted by item. + + If *for_json* is true (default: ``False``), objects with a ``for_json()`` + method will use the return value of that method for encoding as JSON + instead of the object. + + If *ignore_nan* is true (default: ``False``), then out of range + :class:`float` values (``nan``, ``inf``, ``-inf``) will be serialized as + ``null`` in compliance with the ECMA-262 specification. If true, this will + override *allow_nan*. + To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the ``.default()`` method to serialize additional types), specify it with - the ``cls`` kwarg. + the ``cls`` kwarg. NOTE: You should use *default* instead of subclassing + whenever possible. """ # cached encoder - if (not skipkeys and ensure_ascii and + if ( + not skipkeys and ensure_ascii and check_circular and allow_nan and cls is None and indent is None and separators is None and encoding == 'utf-8' and default is None and use_decimal - and namedtuple_as_object and tuple_as_array and not kw): + and namedtuple_as_object and tuple_as_array + and not bigint_as_string and int_as_string_bitcount is None + and not sort_keys and not item_sort_key and not for_json + and not ignore_nan and not kw + ): return _default_encoder.encode(obj) if cls is None: cls = JSONEncoder @@ -293,6 +373,12 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, use_decimal=use_decimal, namedtuple_as_object=namedtuple_as_object, tuple_as_array=tuple_as_array, + bigint_as_string=bigint_as_string, + sort_keys=sort_keys, + item_sort_key=item_sort_key, + for_json=for_json, + ignore_nan=ignore_nan, + int_as_string_bitcount=int_as_string_bitcount, **kw).encode(obj) @@ -347,7 +433,8 @@ def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, parse_float=decimal.Decimal for parity with ``dump``. To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` - kwarg. + kwarg. NOTE: You should use *object_hook* or *object_pairs_hook* instead + of subclassing whenever possible. """ return loads(fp.read(), @@ -403,7 +490,8 @@ def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_float=decimal.Decimal for parity with ``dump``. To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` - kwarg. + kwarg. NOTE: You should use *object_hook* or *object_pairs_hook* instead + of subclassing whenever possible. """ if (cls is None and encoding is None and object_hook is None and @@ -431,14 +519,14 @@ def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, def _toggle_speedups(enabled): - import simplejson.decoder as dec - import simplejson.encoder as enc - import simplejson.scanner as scan + from . import decoder as dec + from . import encoder as enc + from . import scanner as scan c_make_encoder = _import_c_make_encoder() if enabled: dec.scanstring = dec.c_scanstring or dec.py_scanstring enc.c_make_encoder = c_make_encoder - enc.encode_basestring_ascii = (enc.c_encode_basestring_ascii or + enc.encode_basestring_ascii = (enc.c_encode_basestring_ascii or enc.py_encode_basestring_ascii) scan.make_scanner = scan.c_make_scanner or scan.py_make_scanner else: @@ -464,3 +552,9 @@ def _toggle_speedups(enabled): encoding='utf-8', default=None, ) + +def simple_first(kv): + """Helper function to pass to item_sort_key to sort simple + elements to the top, then container elements. + """ + return (isinstance(kv[1], (list, dict, tuple)), kv[0]) diff --git a/module/lib/simplejson/compat.py b/module/lib/simplejson/compat.py new file mode 100644 index 000000000..a0af4a1cb --- /dev/null +++ b/module/lib/simplejson/compat.py @@ -0,0 +1,46 @@ +"""Python 3 compatibility shims +""" +import sys +if sys.version_info[0] < 3: + PY3 = False + def b(s): + return s + def u(s): + return unicode(s, 'unicode_escape') + import cStringIO as StringIO + StringIO = BytesIO = StringIO.StringIO + text_type = unicode + binary_type = str + string_types = (basestring,) + integer_types = (int, long) + unichr = unichr + reload_module = reload + def fromhex(s): + return s.decode('hex') + +else: + PY3 = True + if sys.version_info[:2] >= (3, 4): + from importlib import reload as reload_module + else: + from imp import reload as reload_module + import codecs + def b(s): + return codecs.latin_1_encode(s)[0] + def u(s): + return s + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + text_type = str + binary_type = bytes + string_types = (str,) + integer_types = (int,) + + def unichr(s): + return u(chr(s)) + + def fromhex(s): + return bytes.fromhex(s) + +long_type = integer_types[-1] diff --git a/module/lib/simplejson/decoder.py b/module/lib/simplejson/decoder.py index e5496d6e7..1a6c5d938 100644 --- a/module/lib/simplejson/decoder.py +++ b/module/lib/simplejson/decoder.py @@ -1,24 +1,28 @@ """Implementation of JSONDecoder """ +from __future__ import absolute_import import re import sys import struct +from .compat import fromhex, b, u, text_type, binary_type, PY3, unichr +from .scanner import make_scanner, JSONDecodeError -from simplejson.scanner import make_scanner def _import_c_scanstring(): try: - from simplejson._speedups import scanstring + from ._speedups import scanstring return scanstring except ImportError: return None c_scanstring = _import_c_scanstring() +# NOTE (3.1.0): JSONDecodeError may still be imported from this module for +# compatibility, but it was never in the __all__ __all__ = ['JSONDecoder'] FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL def _floatconstants(): - _BYTES = '7FF80000000000007FF0000000000000'.decode('hex') + _BYTES = fromhex('7FF80000000000007FF0000000000000') # The struct module in Python 2.4 would get frexp() out of range here # when an endian is specified in the format string. Fixed in Python 2.5+ if sys.byteorder != 'big': @@ -28,57 +32,6 @@ def _floatconstants(): NaN, PosInf, NegInf = _floatconstants() - -class JSONDecodeError(ValueError): - """Subclass of ValueError with the following additional properties: - - msg: The unformatted error message - doc: The JSON document being parsed - pos: The start index of doc where parsing failed - end: The end index of doc where parsing failed (may be None) - lineno: The line corresponding to pos - colno: The column corresponding to pos - endlineno: The line corresponding to end (may be None) - endcolno: The column corresponding to end (may be None) - - """ - def __init__(self, msg, doc, pos, end=None): - ValueError.__init__(self, errmsg(msg, doc, pos, end=end)) - self.msg = msg - self.doc = doc - self.pos = pos - self.end = end - self.lineno, self.colno = linecol(doc, pos) - if end is not None: - self.endlineno, self.endcolno = linecol(doc, end) - else: - self.endlineno, self.endcolno = None, None - - -def linecol(doc, pos): - lineno = doc.count('\n', 0, pos) + 1 - if lineno == 1: - colno = pos - else: - colno = pos - doc.rindex('\n', 0, pos) - return lineno, colno - - -def errmsg(msg, doc, pos, end=None): - # Note that this function is called from _speedups - lineno, colno = linecol(doc, pos) - if end is None: - #fmt = '{0}: line {1} column {2} (char {3})' - #return fmt.format(msg, lineno, colno, pos) - fmt = '%s: line %d column %d (char %d)' - return fmt % (msg, lineno, colno, pos) - endlineno, endcolno = linecol(doc, end) - #fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})' - #return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end) - fmt = '%s: line %d column %d - line %d column %d (char %d - %d)' - return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end) - - _CONSTANTS = { '-Infinity': NegInf, 'Infinity': PosInf, @@ -87,14 +40,15 @@ _CONSTANTS = { STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) BACKSLASH = { - '"': u'"', '\\': u'\\', '/': u'/', - 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t', + '"': u('"'), '\\': u('\u005c'), '/': u('/'), + 'b': u('\b'), 'f': u('\f'), 'n': u('\n'), 'r': u('\r'), 't': u('\t'), } DEFAULT_ENCODING = "utf-8" def py_scanstring(s, end, encoding=None, strict=True, - _b=BACKSLASH, _m=STRINGCHUNK.match): + _b=BACKSLASH, _m=STRINGCHUNK.match, _join=u('').join, + _PY3=PY3, _maxunicode=sys.maxunicode): """Scan the string s for a JSON string. End is the index of the character in s after the quote that started the JSON string. Unescapes all valid JSON string escape sequences and raises ValueError @@ -117,8 +71,8 @@ def py_scanstring(s, end, encoding=None, strict=True, content, terminator = chunk.groups() # Content is contains zero or more unescaped string characters if content: - if not isinstance(content, unicode): - content = unicode(content, encoding) + if not _PY3 and not isinstance(content, text_type): + content = text_type(content, encoding) _append(content) # Terminator is the end of string, a literal control character, # or a backslash denoting that an escape sequence follows @@ -126,8 +80,7 @@ def py_scanstring(s, end, encoding=None, strict=True, break elif terminator != '\\': if strict: - msg = "Invalid control character %r at" % (terminator,) - #msg = "Invalid control character {0!r} at".format(terminator) + msg = "Invalid control character %r at" raise JSONDecodeError(msg, s, end) else: _append(terminator) @@ -142,33 +95,42 @@ def py_scanstring(s, end, encoding=None, strict=True, try: char = _b[esc] except KeyError: - msg = "Invalid \\escape: " + repr(esc) + msg = "Invalid \\X escape sequence %r" raise JSONDecodeError(msg, s, end) end += 1 else: # Unicode escape sequence + msg = "Invalid \\uXXXX escape sequence" esc = s[end + 1:end + 5] - next_end = end + 5 - if len(esc) != 4: - msg = "Invalid \\uXXXX escape" - raise JSONDecodeError(msg, s, end) - uni = int(esc, 16) + escX = esc[1:2] + if len(esc) != 4 or escX == 'x' or escX == 'X': + raise JSONDecodeError(msg, s, end - 1) + try: + uni = int(esc, 16) + except ValueError: + raise JSONDecodeError(msg, s, end - 1) + end += 5 # Check for surrogate pair on UCS-4 systems - if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535: - msg = "Invalid \\uXXXX\\uXXXX surrogate pair" - if not s[end + 5:end + 7] == '\\u': - raise JSONDecodeError(msg, s, end) - esc2 = s[end + 7:end + 11] - if len(esc2) != 4: - raise JSONDecodeError(msg, s, end) - uni2 = int(esc2, 16) - uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) - next_end += 6 + # Note that this will join high/low surrogate pairs + # but will also pass unpaired surrogates through + if (_maxunicode > 65535 and + uni & 0xfc00 == 0xd800 and + s[end:end + 2] == '\\u'): + esc2 = s[end + 2:end + 6] + escX = esc2[1:2] + if len(esc2) == 4 and not (escX == 'x' or escX == 'X'): + try: + uni2 = int(esc2, 16) + except ValueError: + raise JSONDecodeError(msg, s, end) + if uni2 & 0xfc00 == 0xdc00: + uni = 0x10000 + (((uni - 0xd800) << 10) | + (uni2 - 0xdc00)) + end += 6 char = unichr(uni) - end = next_end # Append the unescaped character _append(char) - return u''.join(chunks), end + return _join(chunks), end # Use speedup if available @@ -177,9 +139,10 @@ scanstring = c_scanstring or py_scanstring WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) WHITESPACE_STR = ' \t\n\r' -def JSONObject((s, end), encoding, strict, scan_once, object_hook, +def JSONObject(state, encoding, strict, scan_once, object_hook, object_pairs_hook, memo=None, _w=WHITESPACE.match, _ws=WHITESPACE_STR): + (s, end) = state # Backwards compatibility if memo is None: memo = {} @@ -203,7 +166,9 @@ def JSONObject((s, end), encoding, strict, scan_once, object_hook, pairs = object_hook(pairs) return pairs, end + 1 elif nextchar != '"': - raise JSONDecodeError("Expecting property name", s, end) + raise JSONDecodeError( + "Expecting property name enclosed in double quotes", + s, end) end += 1 while True: key, end = scanstring(s, end, encoding, strict) @@ -214,7 +179,7 @@ def JSONObject((s, end), encoding, strict, scan_once, object_hook, if s[end:end + 1] != ':': end = _w(s, end).end() if s[end:end + 1] != ':': - raise JSONDecodeError("Expecting : delimiter", s, end) + raise JSONDecodeError("Expecting ':' delimiter", s, end) end += 1 @@ -226,10 +191,7 @@ def JSONObject((s, end), encoding, strict, scan_once, object_hook, except IndexError: pass - try: - value, end = scan_once(s, end) - except StopIteration: - raise JSONDecodeError("Expecting object", s, end) + value, end = scan_once(s, end) pairs.append((key, value)) try: @@ -244,7 +206,7 @@ def JSONObject((s, end), encoding, strict, scan_once, object_hook, if nextchar == '}': break elif nextchar != ',': - raise JSONDecodeError("Expecting , delimiter", s, end - 1) + raise JSONDecodeError("Expecting ',' delimiter or '}'", s, end - 1) try: nextchar = s[end] @@ -259,7 +221,9 @@ def JSONObject((s, end), encoding, strict, scan_once, object_hook, end += 1 if nextchar != '"': - raise JSONDecodeError("Expecting property name", s, end - 1) + raise JSONDecodeError( + "Expecting property name enclosed in double quotes", + s, end - 1) if object_pairs_hook is not None: result = object_pairs_hook(pairs) @@ -269,7 +233,8 @@ def JSONObject((s, end), encoding, strict, scan_once, object_hook, pairs = object_hook(pairs) return pairs, end -def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): +def JSONArray(state, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): + (s, end) = state values = [] nextchar = s[end:end + 1] if nextchar in _ws: @@ -278,12 +243,11 @@ def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): # Look-ahead for trivial empty array if nextchar == ']': return values, end + 1 + elif nextchar == '': + raise JSONDecodeError("Expecting value or ']'", s, end) _append = values.append while True: - try: - value, end = scan_once(s, end) - except StopIteration: - raise JSONDecodeError("Expecting object", s, end) + value, end = scan_once(s, end) _append(value) nextchar = s[end:end + 1] if nextchar in _ws: @@ -293,7 +257,7 @@ def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): if nextchar == ']': break elif nextchar != ',': - raise JSONDecodeError("Expecting , delimiter", s, end) + raise JSONDecodeError("Expecting ',' delimiter or ']'", s, end - 1) try: if s[end] in _ws: @@ -317,7 +281,7 @@ class JSONDecoder(object): +---------------+-------------------+ | array | list | +---------------+-------------------+ - | string | unicode | + | string | str, unicode | +---------------+-------------------+ | number (int) | int, long | +---------------+-------------------+ @@ -381,6 +345,8 @@ class JSONDecoder(object): ``False`` then control characters will be allowed in strings. """ + if encoding is None: + encoding = DEFAULT_ENCODING self.encoding = encoding self.object_hook = object_hook self.object_pairs_hook = object_pairs_hook @@ -394,28 +360,34 @@ class JSONDecoder(object): self.memo = {} self.scan_once = make_scanner(self) - def decode(self, s, _w=WHITESPACE.match): + def decode(self, s, _w=WHITESPACE.match, _PY3=PY3): """Return the Python representation of ``s`` (a ``str`` or ``unicode`` instance containing a JSON document) """ - obj, end = self.raw_decode(s, idx=_w(s, 0).end()) + if _PY3 and isinstance(s, binary_type): + s = s.decode(self.encoding) + obj, end = self.raw_decode(s) end = _w(s, end).end() if end != len(s): raise JSONDecodeError("Extra data", s, end, len(s)) return obj - def raw_decode(self, s, idx=0): + def raw_decode(self, s, idx=0, _w=WHITESPACE.match, _PY3=PY3): """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning with a JSON document) and return a 2-tuple of the Python representation and the index in ``s`` where the document ended. + Optionally, ``idx`` can be used to specify an offset in ``s`` where + the JSON document begins. This can be used to decode a JSON document from a string that may have extraneous data at the end. """ - try: - obj, end = self.scan_once(s, idx) - except StopIteration: - raise JSONDecodeError("No JSON object could be decoded", s, idx) - return obj, end + if idx < 0: + # Ensure that raw_decode bails on negative indexes, the regex + # would otherwise mask this behavior. #98 + raise JSONDecodeError('Expecting value', s, idx) + if _PY3 and not isinstance(s, text_type): + raise TypeError("Input string must be text, not bytes") + return self.scan_once(s, idx=_w(s, idx).end()) diff --git a/module/lib/simplejson/encoder.py b/module/lib/simplejson/encoder.py index 5ec7440f1..db18244ec 100644 --- a/module/lib/simplejson/encoder.py +++ b/module/lib/simplejson/encoder.py @@ -1,11 +1,13 @@ """Implementation of JSONEncoder """ +from __future__ import absolute_import import re +from operator import itemgetter from decimal import Decimal - +from .compat import u, unichr, binary_type, string_types, integer_types, PY3 def _import_speedups(): try: - from simplejson import _speedups + from . import _speedups return _speedups.encode_basestring_ascii, _speedups.make_encoder except ImportError: return None, None @@ -13,7 +15,10 @@ c_encode_basestring_ascii, c_make_encoder = _import_speedups() from simplejson.decoder import PosInf -ESCAPE = re.compile(ur'[\x00-\x1f\\"\b\f\n\r\t\u2028\u2029]') +#ESCAPE = re.compile(ur'[\x00-\x1f\\"\b\f\n\r\t\u2028\u2029]') +# This is required because u() will mangle the string and ur'' isn't valid +# python3 syntax +ESCAPE = re.compile(u'[\\x00-\\x1f\\\\"\\b\\f\\n\\r\\t\u2028\u2029]') ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') HAS_UTF8 = re.compile(r'[\x80-\xff]') ESCAPE_DCT = { @@ -24,32 +29,40 @@ ESCAPE_DCT = { '\n': '\\n', '\r': '\\r', '\t': '\\t', - u'\u2028': '\\u2028', - u'\u2029': '\\u2029', } for i in range(0x20): #ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) +for i in [0x2028, 0x2029]: + ESCAPE_DCT.setdefault(unichr(i), '\\u%04x' % (i,)) FLOAT_REPR = repr -def encode_basestring(s): +def encode_basestring(s, _PY3=PY3, _q=u('"')): """Return a JSON representation of a Python string """ - if isinstance(s, str) and HAS_UTF8.search(s) is not None: - s = s.decode('utf-8') + if _PY3: + if isinstance(s, binary_type): + s = s.decode('utf-8') + else: + if isinstance(s, str) and HAS_UTF8.search(s) is not None: + s = s.decode('utf-8') def replace(match): return ESCAPE_DCT[match.group(0)] - return u'"' + ESCAPE.sub(replace, s) + u'"' + return _q + ESCAPE.sub(replace, s) + _q -def py_encode_basestring_ascii(s): +def py_encode_basestring_ascii(s, _PY3=PY3): """Return an ASCII-only JSON representation of a Python string """ - if isinstance(s, str) and HAS_UTF8.search(s) is not None: - s = s.decode('utf-8') + if _PY3: + if isinstance(s, binary_type): + s = s.decode('utf-8') + else: + if isinstance(s, str) and HAS_UTF8.search(s) is not None: + s = s.decode('utf-8') def replace(match): s = match.group(0) try: @@ -103,11 +116,14 @@ class JSONEncoder(object): """ item_separator = ', ' key_separator = ': ' + def __init__(self, skipkeys=False, ensure_ascii=True, - check_circular=True, allow_nan=True, sort_keys=False, - indent=None, separators=None, encoding='utf-8', default=None, - use_decimal=True, namedtuple_as_object=True, - tuple_as_array=True): + check_circular=True, allow_nan=True, sort_keys=False, + indent=None, separators=None, encoding='utf-8', default=None, + use_decimal=True, namedtuple_as_object=True, + tuple_as_array=True, bigint_as_string=False, + item_sort_key=None, for_json=False, ignore_nan=False, + int_as_string_bitcount=None): """Constructor for JSONEncoder, with sensible defaults. If skipkeys is false, then it is a TypeError to attempt @@ -139,9 +155,10 @@ class JSONEncoder(object): versions of simplejson earlier than 2.1.0, an integer is also accepted and is converted to a string with that many spaces. - If specified, separators should be a (item_separator, key_separator) - tuple. The default is (', ', ': '). To get the most compact JSON - representation you should specify (',', ':') to eliminate whitespace. + If specified, separators should be an (item_separator, key_separator) + tuple. The default is (', ', ': ') if *indent* is ``None`` and + (',', ': ') otherwise. To get the most compact JSON representation, + you should specify (',', ':') to eliminate whitespace. If specified, default is a function that gets called for objects that can't otherwise be serialized. It should return a JSON encodable @@ -155,11 +172,33 @@ class JSONEncoder(object): be supported directly by the encoder. For the inverse, decode JSON with ``parse_float=decimal.Decimal``. - If namedtuple_as_object is true (the default), tuple subclasses with + If namedtuple_as_object is true (the default), objects with ``_asdict()`` methods will be encoded as JSON objects. - + If tuple_as_array is true (the default), tuple (and subclasses) will be encoded as JSON arrays. + + If bigint_as_string is true (not the default), ints 2**53 and higher + or lower than -2**53 will be encoded as strings. This is to avoid the + rounding that happens in Javascript otherwise. + + If int_as_string_bitcount is a positive number (n), then int of size + greater than or equal to 2**n or lower than or equal to -2**n will be + encoded as strings. + + If specified, item_sort_key is a callable used to sort the items in + each dictionary. This is useful if you want to sort items other than + in alphabetical order by key. + + If for_json is true (not the default), objects with a ``for_json()`` + method will use the return value of that method for encoding as JSON + instead of the object. + + If *ignore_nan* is true (default: ``False``), then out of range + :class:`float` values (``nan``, ``inf``, ``-inf``) will be serialized + as ``null`` in compliance with the ECMA-262 specification. If true, + this will override *allow_nan*. + """ self.skipkeys = skipkeys @@ -170,8 +209,13 @@ class JSONEncoder(object): self.use_decimal = use_decimal self.namedtuple_as_object = namedtuple_as_object self.tuple_as_array = tuple_as_array - if isinstance(indent, (int, long)): - indent = ' ' * indent + self.bigint_as_string = bigint_as_string + self.item_sort_key = item_sort_key + self.for_json = for_json + self.ignore_nan = ignore_nan + self.int_as_string_bitcount = int_as_string_bitcount + if indent is not None and not isinstance(indent, string_types): + indent = indent * ' ' self.indent = indent if separators is not None: self.item_separator, self.key_separator = separators @@ -210,12 +254,11 @@ class JSONEncoder(object): """ # This is for extremely simple cases and benchmarks. - if isinstance(o, basestring): - if isinstance(o, str): - _encoding = self.encoding - if (_encoding is not None - and not (_encoding == 'utf-8')): - o = o.decode(_encoding) + if isinstance(o, binary_type): + _encoding = self.encoding + if (_encoding is not None and not (_encoding == 'utf-8')): + o = o.decode(_encoding) + if isinstance(o, string_types): if self.ensure_ascii: return encode_basestring_ascii(o) else: @@ -251,11 +294,11 @@ class JSONEncoder(object): _encoder = encode_basestring if self.encoding != 'utf-8': def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): - if isinstance(o, str): + if isinstance(o, binary_type): o = o.decode(_encoding) return _orig_encoder(o) - def floatstr(o, allow_nan=self.allow_nan, + def floatstr(o, allow_nan=self.allow_nan, ignore_nan=self.ignore_nan, _repr=FLOAT_REPR, _inf=PosInf, _neginf=-PosInf): # Check for specials. Note that this type of test is processor # and/or platform-specific, so do tests which don't depend on @@ -270,28 +313,37 @@ class JSONEncoder(object): else: return _repr(o) - if not allow_nan: + if ignore_nan: + text = 'null' + elif not allow_nan: raise ValueError( "Out of range float values are not JSON compliant: " + repr(o)) return text - key_memo = {} + int_as_string_bitcount = ( + 53 if self.bigint_as_string else self.int_as_string_bitcount) if (_one_shot and c_make_encoder is not None and self.indent is None): _iterencode = c_make_encoder( markers, self.default, _encoder, self.indent, self.key_separator, self.item_separator, self.sort_keys, self.skipkeys, self.allow_nan, key_memo, self.use_decimal, - self.namedtuple_as_object, self.tuple_as_array) + self.namedtuple_as_object, self.tuple_as_array, + int_as_string_bitcount, + self.item_sort_key, self.encoding, self.for_json, + self.ignore_nan, Decimal) else: _iterencode = _make_iterencode( markers, self.default, _encoder, self.indent, floatstr, self.key_separator, self.item_separator, self.sort_keys, self.skipkeys, _one_shot, self.use_decimal, - self.namedtuple_as_object, self.tuple_as_array) + self.namedtuple_as_object, self.tuple_as_array, + int_as_string_bitcount, + self.item_sort_key, self.encoding, self.for_json, + Decimal=Decimal) try: return _iterencode(o, 0) finally: @@ -328,22 +380,46 @@ class JSONEncoderForHTML(JSONEncoder): def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, _use_decimal, _namedtuple_as_object, _tuple_as_array, + _int_as_string_bitcount, _item_sort_key, + _encoding,_for_json, ## HACK: hand-optimized bytecode; turn globals into locals - False=False, - True=True, + _PY3=PY3, ValueError=ValueError, - basestring=basestring, + string_types=string_types, Decimal=Decimal, dict=dict, float=float, id=id, - int=int, + integer_types=integer_types, isinstance=isinstance, list=list, - long=long, str=str, tuple=tuple, ): + if _item_sort_key and not callable(_item_sort_key): + raise TypeError("item_sort_key must be None or callable") + elif _sort_keys and not _item_sort_key: + _item_sort_key = itemgetter(0) + + if (_int_as_string_bitcount is not None and + (_int_as_string_bitcount <= 0 or + not isinstance(_int_as_string_bitcount, integer_types))): + raise TypeError("int_as_string_bitcount must be a positive integer") + + def _encode_int(value): + skip_quoting = ( + _int_as_string_bitcount is None + or + _int_as_string_bitcount < 1 + ) + if ( + skip_quoting or + (-1 << _int_as_string_bitcount) + < value < + (1 << _int_as_string_bitcount) + ): + return str(value) + return '"' + str(value) + '"' def _iterencode_list(lst, _current_indent_level): if not lst: @@ -369,7 +445,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, first = False else: buf = separator - if isinstance(value, basestring): + if (isinstance(value, string_types) or + (_PY3 and isinstance(value, binary_type))): yield buf + _encoder(value) elif value is None: yield buf + 'null' @@ -377,26 +454,30 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, yield buf + 'true' elif value is False: yield buf + 'false' - elif isinstance(value, (int, long)): - yield buf + str(value) + elif isinstance(value, integer_types): + yield buf + _encode_int(value) elif isinstance(value, float): yield buf + _floatstr(value) elif _use_decimal and isinstance(value, Decimal): yield buf + str(value) else: yield buf - if isinstance(value, list): + for_json = _for_json and getattr(value, 'for_json', None) + if for_json and callable(for_json): + chunks = _iterencode(for_json(), _current_indent_level) + elif isinstance(value, list): chunks = _iterencode_list(value, _current_indent_level) - elif (_namedtuple_as_object and isinstance(value, tuple) and - hasattr(value, '_asdict')): - chunks = _iterencode_dict(value._asdict(), - _current_indent_level) - elif _tuple_as_array and isinstance(value, tuple): - chunks = _iterencode_list(value, _current_indent_level) - elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + _asdict = _namedtuple_as_object and getattr(value, '_asdict', None) + if _asdict and callable(_asdict): + chunks = _iterencode_dict(_asdict(), + _current_indent_level) + elif _tuple_as_array and isinstance(value, tuple): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: @@ -406,6 +487,29 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, if markers is not None: del markers[markerid] + def _stringify_key(key): + if isinstance(key, string_types): # pragma: no cover + pass + elif isinstance(key, binary_type): + key = key.decode(_encoding) + elif isinstance(key, float): + key = _floatstr(key) + elif key is True: + key = 'true' + elif key is False: + key = 'false' + elif key is None: + key = 'null' + elif isinstance(key, integer_types): + key = str(key) + elif _use_decimal and isinstance(key, Decimal): + key = str(key) + elif _skipkeys: + key = None + else: + raise TypeError("key " + repr(key) + " is not a string") + return key + def _iterencode_dict(dct, _current_indent_level): if not dct: yield '{}' @@ -425,37 +529,35 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, newline_indent = None item_separator = _item_separator first = True - if _sort_keys: - items = dct.items() - items.sort(key=lambda kv: kv[0]) + if _PY3: + iteritems = dct.items() else: - items = dct.iteritems() + iteritems = dct.iteritems() + if _item_sort_key: + items = [] + for k, v in dct.items(): + if not isinstance(k, string_types): + k = _stringify_key(k) + if k is None: + continue + items.append((k, v)) + items.sort(key=_item_sort_key) + else: + items = iteritems for key, value in items: - if isinstance(key, basestring): - pass - # JavaScript is weakly typed for these, so it makes sense to - # also allow them. Many encoders seem to do something like this. - elif isinstance(key, float): - key = _floatstr(key) - elif key is True: - key = 'true' - elif key is False: - key = 'false' - elif key is None: - key = 'null' - elif isinstance(key, (int, long)): - key = str(key) - elif _skipkeys: - continue - else: - raise TypeError("key " + repr(key) + " is not a string") + if not (_item_sort_key or isinstance(key, string_types)): + key = _stringify_key(key) + if key is None: + # _skipkeys must be True + continue if first: first = False else: yield item_separator yield _encoder(key) yield _key_separator - if isinstance(value, basestring): + if (isinstance(value, string_types) or + (_PY3 and isinstance(value, binary_type))): yield _encoder(value) elif value is None: yield 'null' @@ -463,25 +565,29 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, yield 'true' elif value is False: yield 'false' - elif isinstance(value, (int, long)): - yield str(value) + elif isinstance(value, integer_types): + yield _encode_int(value) elif isinstance(value, float): yield _floatstr(value) elif _use_decimal and isinstance(value, Decimal): yield str(value) else: - if isinstance(value, list): + for_json = _for_json and getattr(value, 'for_json', None) + if for_json and callable(for_json): + chunks = _iterencode(for_json(), _current_indent_level) + elif isinstance(value, list): chunks = _iterencode_list(value, _current_indent_level) - elif (_namedtuple_as_object and isinstance(value, tuple) and - hasattr(value, '_asdict')): - chunks = _iterencode_dict(value._asdict(), - _current_indent_level) - elif _tuple_as_array and isinstance(value, tuple): - chunks = _iterencode_list(value, _current_indent_level) - elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + _asdict = _namedtuple_as_object and getattr(value, '_asdict', None) + if _asdict and callable(_asdict): + chunks = _iterencode_dict(_asdict(), + _current_indent_level) + elif _tuple_as_array and isinstance(value, tuple): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: @@ -492,7 +598,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, del markers[markerid] def _iterencode(o, _current_indent_level): - if isinstance(o, basestring): + if (isinstance(o, string_types) or + (_PY3 and isinstance(o, binary_type))): yield _encoder(o) elif o is None: yield 'null' @@ -500,35 +607,42 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, yield 'true' elif o is False: yield 'false' - elif isinstance(o, (int, long)): - yield str(o) + elif isinstance(o, integer_types): + yield _encode_int(o) elif isinstance(o, float): yield _floatstr(o) - elif isinstance(o, list): - for chunk in _iterencode_list(o, _current_indent_level): - yield chunk - elif (_namedtuple_as_object and isinstance(o, tuple) and - hasattr(o, '_asdict')): - for chunk in _iterencode_dict(o._asdict(), _current_indent_level): - yield chunk - elif (_tuple_as_array and isinstance(o, tuple)): - for chunk in _iterencode_list(o, _current_indent_level): - yield chunk - elif isinstance(o, dict): - for chunk in _iterencode_dict(o, _current_indent_level): - yield chunk - elif _use_decimal and isinstance(o, Decimal): - yield str(o) else: - if markers is not None: - markerid = id(o) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = o - o = _default(o) - for chunk in _iterencode(o, _current_indent_level): - yield chunk - if markers is not None: - del markers[markerid] + for_json = _for_json and getattr(o, 'for_json', None) + if for_json and callable(for_json): + for chunk in _iterencode(for_json(), _current_indent_level): + yield chunk + elif isinstance(o, list): + for chunk in _iterencode_list(o, _current_indent_level): + yield chunk + else: + _asdict = _namedtuple_as_object and getattr(o, '_asdict', None) + if _asdict and callable(_asdict): + for chunk in _iterencode_dict(_asdict(), + _current_indent_level): + yield chunk + elif (_tuple_as_array and isinstance(o, tuple)): + for chunk in _iterencode_list(o, _current_indent_level): + yield chunk + elif isinstance(o, dict): + for chunk in _iterencode_dict(o, _current_indent_level): + yield chunk + elif _use_decimal and isinstance(o, Decimal): + yield str(o) + else: + if markers is not None: + markerid = id(o) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = o + o = _default(o) + for chunk in _iterencode(o, _current_indent_level): + yield chunk + if markers is not None: + del markers[markerid] return _iterencode diff --git a/module/lib/simplejson/scanner.py b/module/lib/simplejson/scanner.py index 54593a371..5abed357b 100644 --- a/module/lib/simplejson/scanner.py +++ b/module/lib/simplejson/scanner.py @@ -9,12 +9,62 @@ def _import_c_make_scanner(): return None c_make_scanner = _import_c_make_scanner() -__all__ = ['make_scanner'] +__all__ = ['make_scanner', 'JSONDecodeError'] NUMBER_RE = re.compile( r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?', (re.VERBOSE | re.MULTILINE | re.DOTALL)) +class JSONDecodeError(ValueError): + """Subclass of ValueError with the following additional properties: + + msg: The unformatted error message + doc: The JSON document being parsed + pos: The start index of doc where parsing failed + end: The end index of doc where parsing failed (may be None) + lineno: The line corresponding to pos + colno: The column corresponding to pos + endlineno: The line corresponding to end (may be None) + endcolno: The column corresponding to end (may be None) + + """ + # Note that this exception is used from _speedups + def __init__(self, msg, doc, pos, end=None): + ValueError.__init__(self, errmsg(msg, doc, pos, end=end)) + self.msg = msg + self.doc = doc + self.pos = pos + self.end = end + self.lineno, self.colno = linecol(doc, pos) + if end is not None: + self.endlineno, self.endcolno = linecol(doc, end) + else: + self.endlineno, self.endcolno = None, None + + def __reduce__(self): + return self.__class__, (self.msg, self.doc, self.pos, self.end) + + +def linecol(doc, pos): + lineno = doc.count('\n', 0, pos) + 1 + if lineno == 1: + colno = pos + 1 + else: + colno = pos - doc.rindex('\n', 0, pos) + return lineno, colno + + +def errmsg(msg, doc, pos, end=None): + lineno, colno = linecol(doc, pos) + msg = msg.replace('%r', repr(doc[pos:pos + 1])) + if end is None: + fmt = '%s: line %d column %d (char %d)' + return fmt % (msg, lineno, colno, pos) + endlineno, endcolno = linecol(doc, end) + fmt = '%s: line %d column %d - line %d column %d (char %d - %d)' + return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end) + + def py_make_scanner(context): parse_object = context.parse_object parse_array = context.parse_array @@ -30,10 +80,11 @@ def py_make_scanner(context): memo = context.memo def _scan_once(string, idx): + errmsg = 'Expecting value' try: nextchar = string[idx] except IndexError: - raise StopIteration + raise JSONDecodeError(errmsg, string, idx) if nextchar == '"': return parse_string(string, idx + 1, encoding, strict) @@ -64,9 +115,14 @@ def py_make_scanner(context): elif nextchar == '-' and string[idx:idx + 9] == '-Infinity': return parse_constant('-Infinity'), idx + 9 else: - raise StopIteration + raise JSONDecodeError(errmsg, string, idx) def scan_once(string, idx): + if idx < 0: + # Ensure the same behavior as the C speedup, otherwise + # this would work for *some* negative string indices due + # to the behavior of __getitem__ for strings. #98 + raise JSONDecodeError('Expecting value', string, idx) try: return _scan_once(string, idx) finally: diff --git a/module/lib/simplejson/tool.py b/module/lib/simplejson/tool.py index 73370db55..062e8e2c1 100644 --- a/module/lib/simplejson/tool.py +++ b/module/lib/simplejson/tool.py @@ -10,6 +10,7 @@ Usage:: Expecting property name: line 1 column 2 (char 2) """ +from __future__ import with_statement import sys import simplejson as json @@ -18,21 +19,23 @@ def main(): infile = sys.stdin outfile = sys.stdout elif len(sys.argv) == 2: - infile = open(sys.argv[1], 'rb') + infile = open(sys.argv[1], 'r') outfile = sys.stdout elif len(sys.argv) == 3: - infile = open(sys.argv[1], 'rb') - outfile = open(sys.argv[2], 'wb') + infile = open(sys.argv[1], 'r') + outfile = open(sys.argv[2], 'w') else: raise SystemExit(sys.argv[0] + " [infile [outfile]]") - try: - obj = json.load(infile, - object_pairs_hook=json.OrderedDict, - use_decimal=True) - except ValueError, e: - raise SystemExit(e) - json.dump(obj, outfile, sort_keys=True, indent=' ', use_decimal=True) - outfile.write('\n') + with infile: + try: + obj = json.load(infile, + object_pairs_hook=json.OrderedDict, + use_decimal=True) + except ValueError: + raise SystemExit(sys.exc_info()[1]) + with outfile: + json.dump(obj, outfile, sort_keys=True, indent=' ', use_decimal=True) + outfile.write('\n') if __name__ == '__main__': diff --git a/module/lib/thrift/TSCons.py b/module/lib/thrift/TSCons.py index 24046256c..da8d2833b 100644 --- a/module/lib/thrift/TSCons.py +++ b/module/lib/thrift/TSCons.py @@ -20,14 +20,16 @@ from os import path from SCons.Builder import Builder + def scons_env(env, add=''): opath = path.dirname(path.abspath('$TARGET')) lstr = 'thrift --gen cpp -o ' + opath + ' ' + add + ' $SOURCE' - cppbuild = Builder(action = lstr) - env.Append(BUILDERS = {'ThriftCpp' : cppbuild}) + cppbuild = Builder(action=lstr) + env.Append(BUILDERS={'ThriftCpp': cppbuild}) + def gen_cpp(env, dir, file): scons_env(env) suffixes = ['_types.h', '_types.cpp'] targets = map(lambda s: 'gen-cpp/' + file + s, suffixes) - return env.ThriftCpp(targets, dir+file+'.thrift') + return env.ThriftCpp(targets, dir + file + '.thrift') diff --git a/module/lib/thrift/TSerialization.py b/module/lib/thrift/TSerialization.py index b19f98aa8..8a58d89df 100644 --- a/module/lib/thrift/TSerialization.py +++ b/module/lib/thrift/TSerialization.py @@ -20,15 +20,19 @@ from protocol import TBinaryProtocol from transport import TTransport -def serialize(thrift_object, protocol_factory = TBinaryProtocol.TBinaryProtocolFactory()): + +def serialize(thrift_object, + protocol_factory=TBinaryProtocol.TBinaryProtocolFactory()): transport = TTransport.TMemoryBuffer() protocol = protocol_factory.getProtocol(transport) thrift_object.write(protocol) return transport.getvalue() -def deserialize(base, buf, protocol_factory = TBinaryProtocol.TBinaryProtocolFactory()): + +def deserialize(base, + buf, + protocol_factory=TBinaryProtocol.TBinaryProtocolFactory()): transport = TTransport.TMemoryBuffer(buf) protocol = protocol_factory.getProtocol(transport) base.read(protocol) return base - diff --git a/module/lib/thrift/TTornado.py b/module/lib/thrift/TTornado.py new file mode 100644 index 000000000..af309c3d9 --- /dev/null +++ b/module/lib/thrift/TTornado.py @@ -0,0 +1,153 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from cStringIO import StringIO +import logging +import socket +import struct + +from thrift.transport import TTransport +from thrift.transport.TTransport import TTransportException + +from tornado import gen +from tornado import iostream +from tornado import netutil + + +class TTornadoStreamTransport(TTransport.TTransportBase): + """a framed, buffered transport over a Tornado stream""" + def __init__(self, host, port, stream=None): + self.host = host + self.port = port + self.is_queuing_reads = False + self.read_queue = [] + self.__wbuf = StringIO() + + # servers provide a ready-to-go stream + self.stream = stream + if self.stream is not None: + self._set_close_callback() + + # not the same number of parameters as TTransportBase.open + def open(self, callback): + logging.debug('socket connecting') + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + self.stream = iostream.IOStream(sock) + + def on_close_in_connect(*_): + message = 'could not connect to {}:{}'.format(self.host, self.port) + raise TTransportException( + type=TTransportException.NOT_OPEN, + message=message) + self.stream.set_close_callback(on_close_in_connect) + + def finish(*_): + self._set_close_callback() + callback() + + self.stream.connect((self.host, self.port), callback=finish) + + def _set_close_callback(self): + def on_close(): + raise TTransportException( + type=TTransportException.END_OF_FILE, + message='socket closed') + self.stream.set_close_callback(self.close) + + def close(self): + # don't raise if we intend to close + self.stream.set_close_callback(None) + self.stream.close() + + def read(self, _): + # The generated code for Tornado shouldn't do individual reads -- only + # frames at a time + assert "you're doing it wrong" is True + + @gen.engine + def readFrame(self, callback): + self.read_queue.append(callback) + logging.debug('read queue: %s', self.read_queue) + + if self.is_queuing_reads: + # If a read is already in flight, then the while loop below should + # pull it from self.read_queue + return + + self.is_queuing_reads = True + while self.read_queue: + next_callback = self.read_queue.pop() + result = yield gen.Task(self._readFrameFromStream) + next_callback(result) + self.is_queuing_reads = False + + @gen.engine + def _readFrameFromStream(self, callback): + logging.debug('_readFrameFromStream') + frame_header = yield gen.Task(self.stream.read_bytes, 4) + frame_length, = struct.unpack('!i', frame_header) + logging.debug('received frame header, frame length = %i', frame_length) + frame = yield gen.Task(self.stream.read_bytes, frame_length) + logging.debug('received frame payload') + callback(frame) + + def write(self, buf): + self.__wbuf.write(buf) + + def flush(self, callback=None): + wout = self.__wbuf.getvalue() + wsz = len(wout) + # reset wbuf before write/flush to preserve state on underlying failure + self.__wbuf = StringIO() + # N.B.: Doing this string concatenation is WAY cheaper than making + # two separate calls to the underlying socket object. Socket writes in + # Python turn out to be REALLY expensive, but it seems to do a pretty + # good job of managing string buffer operations without excessive copies + buf = struct.pack("!i", wsz) + wout + + logging.debug('writing frame length = %i', wsz) + self.stream.write(buf, callback) + + +class TTornadoServer(netutil.TCPServer): + def __init__(self, processor, iprot_factory, oprot_factory=None, + *args, **kwargs): + super(TTornadoServer, self).__init__(*args, **kwargs) + + self._processor = processor + self._iprot_factory = iprot_factory + self._oprot_factory = (oprot_factory if oprot_factory is not None + else iprot_factory) + + def handle_stream(self, stream, address): + try: + host, port = address + trans = TTornadoStreamTransport(host=host, port=port, stream=stream) + oprot = self._oprot_factory.getProtocol(trans) + + def next_pass(): + if not trans.stream.closed(): + self._processor.process(trans, self._iprot_factory, oprot, + callback=next_pass) + + next_pass() + + except Exception: + logging.exception('thrift exception in handle_stream') + trans.close() diff --git a/module/lib/thrift/Thrift.py b/module/lib/thrift/Thrift.py index 1d271fcff..9890af7e1 100644 --- a/module/lib/thrift/Thrift.py +++ b/module/lib/thrift/Thrift.py @@ -19,6 +19,7 @@ import sys + class TType: STOP = 0 VOID = 1 @@ -38,7 +39,7 @@ class TType: UTF8 = 16 UTF16 = 17 - _VALUES_TO_NAMES = ( 'STOP', + _VALUES_TO_NAMES = ('STOP', 'VOID', 'BOOL', 'BYTE', @@ -48,46 +49,48 @@ class TType: None, 'I32', None, - 'I64', - 'STRING', - 'STRUCT', - 'MAP', - 'SET', - 'LIST', - 'UTF8', - 'UTF16' ) + 'I64', + 'STRING', + 'STRUCT', + 'MAP', + 'SET', + 'LIST', + 'UTF8', + 'UTF16') + class TMessageType: - CALL = 1 + CALL = 1 REPLY = 2 EXCEPTION = 3 ONEWAY = 4 -class TProcessor: +class TProcessor: """Base class for procsessor, which works on two streams.""" def process(iprot, oprot): pass -class TException(Exception): +class TException(Exception): """Base class for all thrift exceptions.""" # BaseException.message is deprecated in Python v[2.6,3.0) - if (2,6,0) <= sys.version_info < (3,0): + if (2, 6, 0) <= sys.version_info < (3, 0): def _get_message(self): - return self._message + return self._message + def _set_message(self, message): - self._message = message + self._message = message message = property(_get_message, _set_message) def __init__(self, message=None): Exception.__init__(self, message) self.message = message -class TApplicationException(TException): +class TApplicationException(TException): """Application level thrift exceptions.""" UNKNOWN = 0 @@ -98,6 +101,9 @@ class TApplicationException(TException): MISSING_RESULT = 5 INTERNAL_ERROR = 6 PROTOCOL_ERROR = 7 + INVALID_TRANSFORM = 8 + INVALID_PROTOCOL = 9 + UNSUPPORTED_CLIENT_TYPE = 10 def __init__(self, type=UNKNOWN, message=None): TException.__init__(self, message) @@ -116,6 +122,16 @@ class TApplicationException(TException): return 'Bad sequence ID' elif self.type == self.MISSING_RESULT: return 'Missing result' + elif self.type == self.INTERNAL_ERROR: + return 'Internal error' + elif self.type == self.PROTOCOL_ERROR: + return 'Protocol error' + elif self.type == self.INVALID_TRANSFORM: + return 'Invalid transform' + elif self.type == self.INVALID_PROTOCOL: + return 'Invalid protocol' + elif self.type == self.UNSUPPORTED_CLIENT_TYPE: + return 'Unsupported client type' else: return 'Default (unknown) TApplicationException' @@ -127,12 +143,12 @@ class TApplicationException(TException): break if fid == 1: if ftype == TType.STRING: - self.message = iprot.readString(); + self.message = iprot.readString() else: iprot.skip(ftype) elif fid == 2: if ftype == TType.I32: - self.type = iprot.readI32(); + self.type = iprot.readI32() else: iprot.skip(ftype) else: @@ -142,11 +158,11 @@ class TApplicationException(TException): def write(self, oprot): oprot.writeStructBegin('TApplicationException') - if self.message != None: + if self.message is not None: oprot.writeFieldBegin('message', TType.STRING, 1) oprot.writeString(self.message) oprot.writeFieldEnd() - if self.type != None: + if self.type is not None: oprot.writeFieldBegin('type', TType.I32, 2) oprot.writeI32(self.type) oprot.writeFieldEnd() diff --git a/module/lib/thrift/protocol/TBase.py b/module/lib/thrift/protocol/TBase.py index e675c7dc0..6cbd5f39a 100644 --- a/module/lib/thrift/protocol/TBase.py +++ b/module/lib/thrift/protocol/TBase.py @@ -26,12 +26,13 @@ try: except: fastbinary = None + class TBase(object): __slots__ = [] def __repr__(self): L = ['%s=%r' % (key, getattr(self, key)) - for key in self.__slots__ ] + for key in self.__slots__] return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) def __eq__(self, other): @@ -43,30 +44,38 @@ class TBase(object): if my_val != other_val: return False return True - + def __ne__(self, other): return not (self == other) - + def read(self, iprot): - if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: - fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) + if (iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and + isinstance(iprot.trans, TTransport.CReadableTransport) and + self.thrift_spec is not None and + fastbinary is not None): + fastbinary.decode_binary(self, + iprot.trans, + (self.__class__, self.thrift_spec)) return iprot.readStruct(self, self.thrift_spec) def write(self, oprot): - if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: - oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) + if (oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and + self.thrift_spec is not None and + fastbinary is not None): + oprot.trans.write( + fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return oprot.writeStruct(self, self.thrift_spec) + class TExceptionBase(Exception): # old style class so python2.4 can raise exceptions derived from this # This can't inherit from TBase because of that limitation. __slots__ = [] - + __repr__ = TBase.__repr__.im_func __eq__ = TBase.__eq__.im_func __ne__ = TBase.__ne__.im_func read = TBase.read.im_func write = TBase.write.im_func - diff --git a/module/lib/thrift/protocol/TBinaryProtocol.py b/module/lib/thrift/protocol/TBinaryProtocol.py index 50c6aa896..6fdd08c26 100644 --- a/module/lib/thrift/protocol/TBinaryProtocol.py +++ b/module/lib/thrift/protocol/TBinaryProtocol.py @@ -20,8 +20,8 @@ from TProtocol import * from struct import pack, unpack -class TBinaryProtocol(TProtocolBase): +class TBinaryProtocol(TProtocolBase): """Binary implementation of the Thrift protocol driver.""" # NastyHaxx. Python 2.4+ on 32-bit machines forces hex constants to be @@ -68,7 +68,7 @@ class TBinaryProtocol(TProtocolBase): pass def writeFieldStop(self): - self.writeByte(TType.STOP); + self.writeByte(TType.STOP) def writeMapBegin(self, ktype, vtype, size): self.writeByte(ktype) @@ -127,13 +127,16 @@ class TBinaryProtocol(TProtocolBase): if sz < 0: version = sz & TBinaryProtocol.VERSION_MASK if version != TBinaryProtocol.VERSION_1: - raise TProtocolException(type=TProtocolException.BAD_VERSION, message='Bad version in readMessageBegin: %d' % (sz)) + raise TProtocolException( + type=TProtocolException.BAD_VERSION, + message='Bad version in readMessageBegin: %d' % (sz)) type = sz & TBinaryProtocol.TYPE_MASK name = self.readString() seqid = self.readI32() else: if self.strictRead: - raise TProtocolException(type=TProtocolException.BAD_VERSION, message='No protocol version header') + raise TProtocolException(type=TProtocolException.BAD_VERSION, + message='No protocol version header') name = self.trans.readAll(sz) type = self.readByte() seqid = self.readI32() @@ -231,7 +234,6 @@ class TBinaryProtocolFactory: class TBinaryProtocolAccelerated(TBinaryProtocol): - """C-Accelerated version of TBinaryProtocol. This class does not override any of TBinaryProtocol's methods, @@ -250,7 +252,6 @@ class TBinaryProtocolAccelerated(TBinaryProtocol): Please feel free to report bugs and/or success stories to the public mailing list. """ - pass diff --git a/module/lib/thrift/protocol/TCompactProtocol.py b/module/lib/thrift/protocol/TCompactProtocol.py index 016a33171..cdec60773 100644 --- a/module/lib/thrift/protocol/TCompactProtocol.py +++ b/module/lib/thrift/protocol/TCompactProtocol.py @@ -32,6 +32,7 @@ CONTAINER_READ = 6 VALUE_READ = 7 BOOL_READ = 8 + def make_helper(v_from, container): def helper(func): def nested(self, *args, **kwargs): @@ -42,12 +43,15 @@ def make_helper(v_from, container): writer = make_helper(VALUE_WRITE, CONTAINER_WRITE) reader = make_helper(VALUE_READ, CONTAINER_READ) + def makeZigZag(n, bits): return (n << 1) ^ (n >> (bits - 1)) + def fromZigZag(n): return (n >> 1) ^ -(n & 1) + def writeVarint(trans, n): out = [] while True: @@ -59,6 +63,7 @@ def writeVarint(trans, n): n = n >> 7 trans.write(''.join(map(chr, out))) + def readVarint(trans): result = 0 shift = 0 @@ -70,6 +75,7 @@ def readVarint(trans): return result shift += 7 + class CompactType: STOP = 0x00 TRUE = 0x01 @@ -86,7 +92,7 @@ class CompactType: STRUCT = 0x0C CTYPES = {TType.STOP: CompactType.STOP, - TType.BOOL: CompactType.TRUE, # used for collection + TType.BOOL: CompactType.TRUE, # used for collection TType.BYTE: CompactType.BYTE, TType.I16: CompactType.I16, TType.I32: CompactType.I32, @@ -106,8 +112,9 @@ TTYPES[CompactType.FALSE] = TType.BOOL del k del v + class TCompactProtocol(TProtocolBase): - "Compact implementation of the Thrift protocol driver." + """Compact implementation of the Thrift protocol driver.""" PROTOCOL_ID = 0x82 VERSION = 1 @@ -217,18 +224,18 @@ class TCompactProtocol(TProtocolBase): def writeBool(self, bool): if self.state == BOOL_WRITE: - if bool: - ctype = CompactType.TRUE - else: - ctype = CompactType.FALSE - self.__writeFieldHeader(ctype, self.__bool_fid) + if bool: + ctype = CompactType.TRUE + else: + ctype = CompactType.FALSE + self.__writeFieldHeader(ctype, self.__bool_fid) elif self.state == CONTAINER_WRITE: - if bool: - self.__writeByte(CompactType.TRUE) - else: - self.__writeByte(CompactType.FALSE) + if bool: + self.__writeByte(CompactType.TRUE) + else: + self.__writeByte(CompactType.FALSE) else: - raise AssertionError, "Invalid state in compact protocol" + raise AssertionError("Invalid state in compact protocol") writeByte = writer(__writeByte) writeI16 = writer(__writeI16) @@ -364,7 +371,8 @@ class TCompactProtocol(TProtocolBase): elif self.state == CONTAINER_READ: return self.__readByte() == CompactType.TRUE else: - raise AssertionError, "Invalid state in compact protocol: %d" % self.state + raise AssertionError("Invalid state in compact protocol: %d" % + self.state) readByte = reader(__readByte) __readI16 = __readZigZag diff --git a/module/lib/thrift/protocol/TJSONProtocol.py b/module/lib/thrift/protocol/TJSONProtocol.py new file mode 100644 index 000000000..3048197d4 --- /dev/null +++ b/module/lib/thrift/protocol/TJSONProtocol.py @@ -0,0 +1,550 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from TProtocol import TType, TProtocolBase, TProtocolException +import base64 +import json +import math + +__all__ = ['TJSONProtocol', + 'TJSONProtocolFactory', + 'TSimpleJSONProtocol', + 'TSimpleJSONProtocolFactory'] + +VERSION = 1 + +COMMA = ',' +COLON = ':' +LBRACE = '{' +RBRACE = '}' +LBRACKET = '[' +RBRACKET = ']' +QUOTE = '"' +BACKSLASH = '\\' +ZERO = '0' + +ESCSEQ = '\\u00' +ESCAPE_CHAR = '"\\bfnrt' +ESCAPE_CHAR_VALS = ['"', '\\', '\b', '\f', '\n', '\r', '\t'] +NUMERIC_CHAR = '+-.0123456789Ee' + +CTYPES = {TType.BOOL: 'tf', + TType.BYTE: 'i8', + TType.I16: 'i16', + TType.I32: 'i32', + TType.I64: 'i64', + TType.DOUBLE: 'dbl', + TType.STRING: 'str', + TType.STRUCT: 'rec', + TType.LIST: 'lst', + TType.SET: 'set', + TType.MAP: 'map'} + +JTYPES = {} +for key in CTYPES.keys(): + JTYPES[CTYPES[key]] = key + + +class JSONBaseContext(object): + + def __init__(self, protocol): + self.protocol = protocol + self.first = True + + def doIO(self, function): + pass + + def write(self): + pass + + def read(self): + pass + + def escapeNum(self): + return False + + def __str__(self): + return self.__class__.__name__ + + +class JSONListContext(JSONBaseContext): + + def doIO(self, function): + if self.first is True: + self.first = False + else: + function(COMMA) + + def write(self): + self.doIO(self.protocol.trans.write) + + def read(self): + self.doIO(self.protocol.readJSONSyntaxChar) + + +class JSONPairContext(JSONBaseContext): + + def __init__(self, protocol): + super(JSONPairContext, self).__init__(protocol) + self.colon = True + + def doIO(self, function): + if self.first: + self.first = False + self.colon = True + else: + function(COLON if self.colon else COMMA) + self.colon = not self.colon + + def write(self): + self.doIO(self.protocol.trans.write) + + def read(self): + self.doIO(self.protocol.readJSONSyntaxChar) + + def escapeNum(self): + return self.colon + + def __str__(self): + return '%s, colon=%s' % (self.__class__.__name__, self.colon) + + +class LookaheadReader(): + hasData = False + data = '' + + def __init__(self, protocol): + self.protocol = protocol + + def read(self): + if self.hasData is True: + self.hasData = False + else: + self.data = self.protocol.trans.read(1) + return self.data + + def peek(self): + if self.hasData is False: + self.data = self.protocol.trans.read(1) + self.hasData = True + return self.data + +class TJSONProtocolBase(TProtocolBase): + + def __init__(self, trans): + TProtocolBase.__init__(self, trans) + self.resetWriteContext() + self.resetReadContext() + + def resetWriteContext(self): + self.context = JSONBaseContext(self) + self.contextStack = [self.context] + + def resetReadContext(self): + self.resetWriteContext() + self.reader = LookaheadReader(self) + + def pushContext(self, ctx): + self.contextStack.append(ctx) + self.context = ctx + + def popContext(self): + self.contextStack.pop() + if self.contextStack: + self.context = self.contextStack[-1] + else: + self.context = JSONBaseContext(self) + + def writeJSONString(self, string): + self.context.write() + self.trans.write(json.dumps(string)) + + def writeJSONNumber(self, number): + self.context.write() + jsNumber = str(number) + if self.context.escapeNum(): + jsNumber = "%s%s%s" % (QUOTE, jsNumber, QUOTE) + self.trans.write(jsNumber) + + def writeJSONBase64(self, binary): + self.context.write() + self.trans.write(QUOTE) + self.trans.write(base64.b64encode(binary)) + self.trans.write(QUOTE) + + def writeJSONObjectStart(self): + self.context.write() + self.trans.write(LBRACE) + self.pushContext(JSONPairContext(self)) + + def writeJSONObjectEnd(self): + self.popContext() + self.trans.write(RBRACE) + + def writeJSONArrayStart(self): + self.context.write() + self.trans.write(LBRACKET) + self.pushContext(JSONListContext(self)) + + def writeJSONArrayEnd(self): + self.popContext() + self.trans.write(RBRACKET) + + def readJSONSyntaxChar(self, character): + current = self.reader.read() + if character != current: + raise TProtocolException(TProtocolException.INVALID_DATA, + "Unexpected character: %s" % current) + + def readJSONString(self, skipContext): + string = [] + if skipContext is False: + self.context.read() + self.readJSONSyntaxChar(QUOTE) + while True: + character = self.reader.read() + if character == QUOTE: + break + if character == ESCSEQ[0]: + character = self.reader.read() + if character == ESCSEQ[1]: + self.readJSONSyntaxChar(ZERO) + self.readJSONSyntaxChar(ZERO) + character = json.JSONDecoder().decode('"\u00%s"' % self.trans.read(2)) + else: + off = ESCAPE_CHAR.find(character) + if off == -1: + raise TProtocolException(TProtocolException.INVALID_DATA, + "Expected control char") + character = ESCAPE_CHAR_VALS[off] + string.append(character) + return ''.join(string) + + def isJSONNumeric(self, character): + return (True if NUMERIC_CHAR.find(character) != - 1 else False) + + def readJSONQuotes(self): + if (self.context.escapeNum()): + self.readJSONSyntaxChar(QUOTE) + + def readJSONNumericChars(self): + numeric = [] + while True: + character = self.reader.peek() + if self.isJSONNumeric(character) is False: + break + numeric.append(self.reader.read()) + return ''.join(numeric) + + def readJSONInteger(self): + self.context.read() + self.readJSONQuotes() + numeric = self.readJSONNumericChars() + self.readJSONQuotes() + try: + return int(numeric) + except ValueError: + raise TProtocolException(TProtocolException.INVALID_DATA, + "Bad data encounted in numeric data") + + def readJSONDouble(self): + self.context.read() + if self.reader.peek() == QUOTE: + string = self.readJSONString(True) + try: + double = float(string) + if (self.context.escapeNum is False and + not math.isinf(double) and + not math.isnan(double)): + raise TProtocolException(TProtocolException.INVALID_DATA, + "Numeric data unexpectedly quoted") + return double + except ValueError: + raise TProtocolException(TProtocolException.INVALID_DATA, + "Bad data encounted in numeric data") + else: + if self.context.escapeNum() is True: + self.readJSONSyntaxChar(QUOTE) + try: + return float(self.readJSONNumericChars()) + except ValueError: + raise TProtocolException(TProtocolException.INVALID_DATA, + "Bad data encounted in numeric data") + + def readJSONBase64(self): + string = self.readJSONString(False) + return base64.b64decode(string) + + def readJSONObjectStart(self): + self.context.read() + self.readJSONSyntaxChar(LBRACE) + self.pushContext(JSONPairContext(self)) + + def readJSONObjectEnd(self): + self.readJSONSyntaxChar(RBRACE) + self.popContext() + + def readJSONArrayStart(self): + self.context.read() + self.readJSONSyntaxChar(LBRACKET) + self.pushContext(JSONListContext(self)) + + def readJSONArrayEnd(self): + self.readJSONSyntaxChar(RBRACKET) + self.popContext() + + +class TJSONProtocol(TJSONProtocolBase): + + def readMessageBegin(self): + self.resetReadContext() + self.readJSONArrayStart() + if self.readJSONInteger() != VERSION: + raise TProtocolException(TProtocolException.BAD_VERSION, + "Message contained bad version.") + name = self.readJSONString(False) + typen = self.readJSONInteger() + seqid = self.readJSONInteger() + return (name, typen, seqid) + + def readMessageEnd(self): + self.readJSONArrayEnd() + + def readStructBegin(self): + self.readJSONObjectStart() + + def readStructEnd(self): + self.readJSONObjectEnd() + + def readFieldBegin(self): + character = self.reader.peek() + ttype = 0 + id = 0 + if character == RBRACE: + ttype = TType.STOP + else: + id = self.readJSONInteger() + self.readJSONObjectStart() + ttype = JTYPES[self.readJSONString(False)] + return (None, ttype, id) + + def readFieldEnd(self): + self.readJSONObjectEnd() + + def readMapBegin(self): + self.readJSONArrayStart() + keyType = JTYPES[self.readJSONString(False)] + valueType = JTYPES[self.readJSONString(False)] + size = self.readJSONInteger() + self.readJSONObjectStart() + return (keyType, valueType, size) + + def readMapEnd(self): + self.readJSONObjectEnd() + self.readJSONArrayEnd() + + def readCollectionBegin(self): + self.readJSONArrayStart() + elemType = JTYPES[self.readJSONString(False)] + size = self.readJSONInteger() + return (elemType, size) + readListBegin = readCollectionBegin + readSetBegin = readCollectionBegin + + def readCollectionEnd(self): + self.readJSONArrayEnd() + readSetEnd = readCollectionEnd + readListEnd = readCollectionEnd + + def readBool(self): + return (False if self.readJSONInteger() == 0 else True) + + def readNumber(self): + return self.readJSONInteger() + readByte = readNumber + readI16 = readNumber + readI32 = readNumber + readI64 = readNumber + + def readDouble(self): + return self.readJSONDouble() + + def readString(self): + return self.readJSONString(False) + + def readBinary(self): + return self.readJSONBase64() + + def writeMessageBegin(self, name, request_type, seqid): + self.resetWriteContext() + self.writeJSONArrayStart() + self.writeJSONNumber(VERSION) + self.writeJSONString(name) + self.writeJSONNumber(request_type) + self.writeJSONNumber(seqid) + + def writeMessageEnd(self): + self.writeJSONArrayEnd() + + def writeStructBegin(self, name): + self.writeJSONObjectStart() + + def writeStructEnd(self): + self.writeJSONObjectEnd() + + def writeFieldBegin(self, name, ttype, id): + self.writeJSONNumber(id) + self.writeJSONObjectStart() + self.writeJSONString(CTYPES[ttype]) + + def writeFieldEnd(self): + self.writeJSONObjectEnd() + + def writeFieldStop(self): + pass + + def writeMapBegin(self, ktype, vtype, size): + self.writeJSONArrayStart() + self.writeJSONString(CTYPES[ktype]) + self.writeJSONString(CTYPES[vtype]) + self.writeJSONNumber(size) + self.writeJSONObjectStart() + + def writeMapEnd(self): + self.writeJSONObjectEnd() + self.writeJSONArrayEnd() + + def writeListBegin(self, etype, size): + self.writeJSONArrayStart() + self.writeJSONString(CTYPES[etype]) + self.writeJSONNumber(size) + + def writeListEnd(self): + self.writeJSONArrayEnd() + + def writeSetBegin(self, etype, size): + self.writeJSONArrayStart() + self.writeJSONString(CTYPES[etype]) + self.writeJSONNumber(size) + + def writeSetEnd(self): + self.writeJSONArrayEnd() + + def writeBool(self, boolean): + self.writeJSONNumber(1 if boolean is True else 0) + + def writeInteger(self, integer): + self.writeJSONNumber(integer) + writeByte = writeInteger + writeI16 = writeInteger + writeI32 = writeInteger + writeI64 = writeInteger + + def writeDouble(self, dbl): + self.writeJSONNumber(dbl) + + def writeString(self, string): + self.writeJSONString(string) + + def writeBinary(self, binary): + self.writeJSONBase64(binary) + + +class TJSONProtocolFactory: + + def getProtocol(self, trans): + return TJSONProtocol(trans) + + +class TSimpleJSONProtocol(TJSONProtocolBase): + """Simple, readable, write-only JSON protocol. + + Useful for interacting with scripting languages. + """ + + def readMessageBegin(self): + raise NotImplementedError() + + def readMessageEnd(self): + raise NotImplementedError() + + def readStructBegin(self): + raise NotImplementedError() + + def readStructEnd(self): + raise NotImplementedError() + + def writeMessageBegin(self, name, request_type, seqid): + self.resetWriteContext() + + def writeMessageEnd(self): + pass + + def writeStructBegin(self, name): + self.writeJSONObjectStart() + + def writeStructEnd(self): + self.writeJSONObjectEnd() + + def writeFieldBegin(self, name, ttype, fid): + self.writeJSONString(name) + + def writeFieldEnd(self): + pass + + def writeMapBegin(self, ktype, vtype, size): + self.writeJSONObjectStart() + + def writeMapEnd(self): + self.writeJSONObjectEnd() + + def _writeCollectionBegin(self, etype, size): + self.writeJSONArrayStart() + + def _writeCollectionEnd(self): + self.writeJSONArrayEnd() + writeListBegin = _writeCollectionBegin + writeListEnd = _writeCollectionEnd + writeSetBegin = _writeCollectionBegin + writeSetEnd = _writeCollectionEnd + + def writeInteger(self, integer): + self.writeJSONNumber(integer) + writeByte = writeInteger + writeI16 = writeInteger + writeI32 = writeInteger + writeI64 = writeInteger + + def writeBool(self, boolean): + self.writeJSONNumber(1 if boolean is True else 0) + + def writeDouble(self, dbl): + self.writeJSONNumber(dbl) + + def writeString(self, string): + self.writeJSONString(string) + + def writeBinary(self, binary): + self.writeJSONBase64(binary) + + +class TSimpleJSONProtocolFactory(object): + + def getProtocol(self, trans): + return TSimpleJSONProtocol(trans) diff --git a/module/lib/thrift/protocol/TProtocol.py b/module/lib/thrift/protocol/TProtocol.py index 7338ff68a..dc2b095de 100644 --- a/module/lib/thrift/protocol/TProtocol.py +++ b/module/lib/thrift/protocol/TProtocol.py @@ -19,8 +19,8 @@ from thrift.Thrift import * -class TProtocolException(TException): +class TProtocolException(TException): """Custom Protocol Exception class""" UNKNOWN = 0 @@ -33,14 +33,14 @@ class TProtocolException(TException): TException.__init__(self, message) self.type = type -class TProtocolBase: +class TProtocolBase: """Base class for Thrift protocol driver.""" def __init__(self, trans): self.trans = trans - def writeMessageBegin(self, name, type, seqid): + def writeMessageBegin(self, name, ttype, seqid): pass def writeMessageEnd(self): @@ -52,7 +52,7 @@ class TProtocolBase: def writeStructEnd(self): pass - def writeFieldBegin(self, name, type, id): + def writeFieldBegin(self, name, ttype, fid): pass def writeFieldEnd(self): @@ -79,7 +79,7 @@ class TProtocolBase: def writeSetEnd(self): pass - def writeBool(self, bool): + def writeBool(self, bool_val): pass def writeByte(self, byte): @@ -97,7 +97,7 @@ class TProtocolBase: def writeDouble(self, dub): pass - def writeString(self, str): + def writeString(self, str_val): pass def readMessageBegin(self): @@ -157,69 +157,69 @@ class TProtocolBase: def readString(self): pass - def skip(self, type): - if type == TType.STOP: + def skip(self, ttype): + if ttype == TType.STOP: return - elif type == TType.BOOL: + elif ttype == TType.BOOL: self.readBool() - elif type == TType.BYTE: + elif ttype == TType.BYTE: self.readByte() - elif type == TType.I16: + elif ttype == TType.I16: self.readI16() - elif type == TType.I32: + elif ttype == TType.I32: self.readI32() - elif type == TType.I64: + elif ttype == TType.I64: self.readI64() - elif type == TType.DOUBLE: + elif ttype == TType.DOUBLE: self.readDouble() - elif type == TType.STRING: + elif ttype == TType.STRING: self.readString() - elif type == TType.STRUCT: + elif ttype == TType.STRUCT: name = self.readStructBegin() while True: - (name, type, id) = self.readFieldBegin() - if type == TType.STOP: + (name, ttype, id) = self.readFieldBegin() + if ttype == TType.STOP: break - self.skip(type) + self.skip(ttype) self.readFieldEnd() self.readStructEnd() - elif type == TType.MAP: + elif ttype == TType.MAP: (ktype, vtype, size) = self.readMapBegin() - for i in range(size): + for i in xrange(size): self.skip(ktype) self.skip(vtype) self.readMapEnd() - elif type == TType.SET: + elif ttype == TType.SET: (etype, size) = self.readSetBegin() - for i in range(size): + for i in xrange(size): self.skip(etype) self.readSetEnd() - elif type == TType.LIST: + elif ttype == TType.LIST: (etype, size) = self.readListBegin() - for i in range(size): + for i in xrange(size): self.skip(etype) self.readListEnd() - # tuple of: ( 'reader method' name, is_container boolean, 'writer_method' name ) + # tuple of: ( 'reader method' name, is_container bool, 'writer_method' name ) _TTYPE_HANDLERS = ( - (None, None, False), # 0 == TType,STOP - (None, None, False), # 1 == TType.VOID # TODO: handle void? - ('readBool', 'writeBool', False), # 2 == TType.BOOL - ('readByte', 'writeByte', False), # 3 == TType.BYTE and I08 - ('readDouble', 'writeDouble', False), # 4 == TType.DOUBLE - (None, None, False), # 5, undefined - ('readI16', 'writeI16', False), # 6 == TType.I16 - (None, None, False), # 7, undefined - ('readI32', 'writeI32', False), # 8 == TType.I32 - (None, None, False), # 9, undefined - ('readI64', 'writeI64', False), # 10 == TType.I64 - ('readString', 'writeString', False), # 11 == TType.STRING and UTF7 - ('readContainerStruct', 'writeContainerStruct', True), # 12 == TType.STRUCT - ('readContainerMap', 'writeContainerMap', True), # 13 == TType.MAP - ('readContainerSet', 'writeContainerSet', True), # 14 == TType.SET - ('readContainerList', 'writeContainerList', True), # 15 == TType.LIST - (None, None, False), # 16 == TType.UTF8 # TODO: handle utf8 types? - (None, None, False)# 17 == TType.UTF16 # TODO: handle utf16 types? + (None, None, False), # 0 TType.STOP + (None, None, False), # 1 TType.VOID # TODO: handle void? + ('readBool', 'writeBool', False), # 2 TType.BOOL + ('readByte', 'writeByte', False), # 3 TType.BYTE and I08 + ('readDouble', 'writeDouble', False), # 4 TType.DOUBLE + (None, None, False), # 5 undefined + ('readI16', 'writeI16', False), # 6 TType.I16 + (None, None, False), # 7 undefined + ('readI32', 'writeI32', False), # 8 TType.I32 + (None, None, False), # 9 undefined + ('readI64', 'writeI64', False), # 10 TType.I64 + ('readString', 'writeString', False), # 11 TType.STRING and UTF7 + ('readContainerStruct', 'writeContainerStruct', True), # 12 *.STRUCT + ('readContainerMap', 'writeContainerMap', True), # 13 TType.MAP + ('readContainerSet', 'writeContainerSet', True), # 14 TType.SET + ('readContainerList', 'writeContainerList', True), # 15 TType.LIST + (None, None, False), # 16 TType.UTF8 # TODO: handle utf8 types? + (None, None, False) # 17 TType.UTF16 # TODO: handle utf16 types? ) def readFieldByTType(self, ttype, spec): @@ -270,7 +270,7 @@ class TProtocolBase: container_reader = self._TTYPE_HANDLERS[set_type][0] val_reader = getattr(self, container_reader) for idx in xrange(set_len): - results.add(val_reader(tspec)) + results.add(val_reader(tspec)) self.readSetEnd() return results @@ -279,13 +279,14 @@ class TProtocolBase: obj = obj_class() obj.read(self) return obj - + def readContainerMap(self, spec): results = dict() key_ttype, key_spec = spec[0], spec[1] val_ttype, val_spec = spec[2], spec[3] (map_ktype, map_vtype, map_len) = self.readMapBegin() - # TODO: compare types we just decoded with thrift_spec and abort/skip if types disagree + # TODO: compare types we just decoded with thrift_spec and + # abort/skip if types disagree key_reader = getattr(self, self._TTYPE_HANDLERS[key_ttype][0]) val_reader = getattr(self, self._TTYPE_HANDLERS[val_ttype][0]) # list values are simple types @@ -298,7 +299,8 @@ class TProtocolBase: v_val = val_reader() else: v_val = self.readFieldByTType(val_ttype, val_spec) - # this raises a TypeError with unhashable keys types. i.e. d=dict(); d[[0,1]] = 2 fails + # this raises a TypeError with unhashable keys types + # i.e. this fails: d=dict(); d[[0,1]] = 2 results[k_val] = v_val self.readMapEnd() return results @@ -329,7 +331,7 @@ class TProtocolBase: def writeContainerList(self, val, spec): self.writeListBegin(spec[0], len(val)) - r_handler, w_handler, is_container = self._TTYPE_HANDLERS[spec[0]] + r_handler, w_handler, is_container = self._TTYPE_HANDLERS[spec[0]] e_writer = getattr(self, w_handler) if not is_container: for elem in val: @@ -398,7 +400,7 @@ class TProtocolBase: else: writer(val) + class TProtocolFactory: def getProtocol(self, trans): pass - diff --git a/module/lib/thrift/protocol/__init__.py b/module/lib/thrift/protocol/__init__.py index d53359b28..7eefb458a 100644 --- a/module/lib/thrift/protocol/__init__.py +++ b/module/lib/thrift/protocol/__init__.py @@ -17,4 +17,4 @@ # under the License. # -__all__ = ['TProtocol', 'TBinaryProtocol', 'fastbinary', 'TBase'] +__all__ = ['fastbinary', 'TBase', 'TBinaryProtocol', 'TCompactProtocol', 'TJSONProtocol', 'TProtocol'] diff --git a/module/lib/thrift/protocol/fastbinary.c b/module/lib/thrift/protocol/fastbinary.c new file mode 100644 index 000000000..2ce56603c --- /dev/null +++ b/module/lib/thrift/protocol/fastbinary.c @@ -0,0 +1,1219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <Python.h> +#include "cStringIO.h" +#include <stdint.h> +#ifndef _WIN32 +# include <stdbool.h> +# include <netinet/in.h> +#else +# include <WinSock2.h> +# pragma comment (lib, "ws2_32.lib") +# define BIG_ENDIAN (4321) +# define LITTLE_ENDIAN (1234) +# define BYTE_ORDER LITTLE_ENDIAN +# if defined(_MSC_VER) && _MSC_VER < 1600 + typedef int _Bool; +# define bool _Bool +# define false 0 +# define true 1 +# endif +# define inline __inline +#endif + +/* Fix endianness issues on Solaris */ +#if defined (__SVR4) && defined (__sun) + #if defined(__i386) && !defined(__i386__) + #define __i386__ + #endif + + #ifndef BIG_ENDIAN + #define BIG_ENDIAN (4321) + #endif + #ifndef LITTLE_ENDIAN + #define LITTLE_ENDIAN (1234) + #endif + + /* I386 is LE, even on Solaris */ + #if !defined(BYTE_ORDER) && defined(__i386__) + #define BYTE_ORDER LITTLE_ENDIAN + #endif +#endif + +// TODO(dreiss): defval appears to be unused. Look into removing it. +// TODO(dreiss): Make parse_spec_args recursive, and cache the output +// permanently in the object. (Malloc and orphan.) +// TODO(dreiss): Why do we need cStringIO for reading, why not just char*? +// Can cStringIO let us work with a BufferedTransport? +// TODO(dreiss): Don't ignore the rv from cwrite (maybe). + +/* ====== BEGIN UTILITIES ====== */ + +#define INIT_OUTBUF_SIZE 128 + +// Stolen out of TProtocol.h. +// It would be a huge pain to have both get this from one place. +typedef enum TType { + T_STOP = 0, + T_VOID = 1, + T_BOOL = 2, + T_BYTE = 3, + T_I08 = 3, + T_I16 = 6, + T_I32 = 8, + T_U64 = 9, + T_I64 = 10, + T_DOUBLE = 4, + T_STRING = 11, + T_UTF7 = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + T_UTF8 = 16, + T_UTF16 = 17 +} TType; + +#ifndef __BYTE_ORDER +# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define __BYTE_ORDER BYTE_ORDER +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +# else +# error "Cannot determine endianness" +# endif +#endif + +// Same comment as the enum. Sorry. +#if __BYTE_ORDER == __BIG_ENDIAN +# define ntohll(n) (n) +# define htonll(n) (n) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# if defined(__GNUC__) && defined(__GLIBC__) +# include <byteswap.h> +# define ntohll(n) bswap_64(n) +# define htonll(n) bswap_64(n) +# else /* GNUC & GLIBC */ +# define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) ) +# define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) ) +# endif /* GNUC & GLIBC */ +#else /* __BYTE_ORDER */ +# error "Can't define htonll or ntohll!" +#endif + +// Doing a benchmark shows that interning actually makes a difference, amazingly. +#define INTERN_STRING(value) _intern_ ## value + +#define INT_CONV_ERROR_OCCURRED(v) ( ((v) == -1) && PyErr_Occurred() ) +#define CHECK_RANGE(v, min, max) ( ((v) <= (max)) && ((v) >= (min)) ) + +// Py_ssize_t was not defined before Python 2.5 +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +/** + * A cache of the spec_args for a set or list, + * so we don't have to keep calling PyTuple_GET_ITEM. + */ +typedef struct { + TType element_type; + PyObject* typeargs; +} SetListTypeArgs; + +/** + * A cache of the spec_args for a map, + * so we don't have to keep calling PyTuple_GET_ITEM. + */ +typedef struct { + TType ktag; + TType vtag; + PyObject* ktypeargs; + PyObject* vtypeargs; +} MapTypeArgs; + +/** + * A cache of the spec_args for a struct, + * so we don't have to keep calling PyTuple_GET_ITEM. + */ +typedef struct { + PyObject* klass; + PyObject* spec; +} StructTypeArgs; + +/** + * A cache of the item spec from a struct specification, + * so we don't have to keep calling PyTuple_GET_ITEM. + */ +typedef struct { + int tag; + TType type; + PyObject* attrname; + PyObject* typeargs; + PyObject* defval; +} StructItemSpec; + +/** + * A cache of the two key attributes of a CReadableTransport, + * so we don't have to keep calling PyObject_GetAttr. + */ +typedef struct { + PyObject* stringiobuf; + PyObject* refill_callable; +} DecodeBuffer; + +/** Pointer to interned string to speed up attribute lookup. */ +static PyObject* INTERN_STRING(cstringio_buf); +/** Pointer to interned string to speed up attribute lookup. */ +static PyObject* INTERN_STRING(cstringio_refill); + +static inline bool +check_ssize_t_32(Py_ssize_t len) { + // error from getting the int + if (INT_CONV_ERROR_OCCURRED(len)) { + return false; + } + if (!CHECK_RANGE(len, 0, INT32_MAX)) { + PyErr_SetString(PyExc_OverflowError, "string size out of range"); + return false; + } + return true; +} + +static inline bool +parse_pyint(PyObject* o, int32_t* ret, int32_t min, int32_t max) { + long val = PyInt_AsLong(o); + + if (INT_CONV_ERROR_OCCURRED(val)) { + return false; + } + if (!CHECK_RANGE(val, min, max)) { + PyErr_SetString(PyExc_OverflowError, "int out of range"); + return false; + } + + *ret = (int32_t) val; + return true; +} + + +/* --- FUNCTIONS TO PARSE STRUCT SPECIFICATOINS --- */ + +static bool +parse_set_list_args(SetListTypeArgs* dest, PyObject* typeargs) { + if (PyTuple_Size(typeargs) != 2) { + PyErr_SetString(PyExc_TypeError, "expecting tuple of size 2 for list/set type args"); + return false; + } + + dest->element_type = PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 0)); + if (INT_CONV_ERROR_OCCURRED(dest->element_type)) { + return false; + } + + dest->typeargs = PyTuple_GET_ITEM(typeargs, 1); + + return true; +} + +static bool +parse_map_args(MapTypeArgs* dest, PyObject* typeargs) { + if (PyTuple_Size(typeargs) != 4) { + PyErr_SetString(PyExc_TypeError, "expecting 4 arguments for typeargs to map"); + return false; + } + + dest->ktag = PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 0)); + if (INT_CONV_ERROR_OCCURRED(dest->ktag)) { + return false; + } + + dest->vtag = PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 2)); + if (INT_CONV_ERROR_OCCURRED(dest->vtag)) { + return false; + } + + dest->ktypeargs = PyTuple_GET_ITEM(typeargs, 1); + dest->vtypeargs = PyTuple_GET_ITEM(typeargs, 3); + + return true; +} + +static bool +parse_struct_args(StructTypeArgs* dest, PyObject* typeargs) { + if (PyTuple_Size(typeargs) != 2) { + PyErr_SetString(PyExc_TypeError, "expecting tuple of size 2 for struct args"); + return false; + } + + dest->klass = PyTuple_GET_ITEM(typeargs, 0); + dest->spec = PyTuple_GET_ITEM(typeargs, 1); + + return true; +} + +static int +parse_struct_item_spec(StructItemSpec* dest, PyObject* spec_tuple) { + + // i'd like to use ParseArgs here, but it seems to be a bottleneck. + if (PyTuple_Size(spec_tuple) != 5) { + PyErr_SetString(PyExc_TypeError, "expecting 5 arguments for spec tuple"); + return false; + } + + dest->tag = PyInt_AsLong(PyTuple_GET_ITEM(spec_tuple, 0)); + if (INT_CONV_ERROR_OCCURRED(dest->tag)) { + return false; + } + + dest->type = PyInt_AsLong(PyTuple_GET_ITEM(spec_tuple, 1)); + if (INT_CONV_ERROR_OCCURRED(dest->type)) { + return false; + } + + dest->attrname = PyTuple_GET_ITEM(spec_tuple, 2); + dest->typeargs = PyTuple_GET_ITEM(spec_tuple, 3); + dest->defval = PyTuple_GET_ITEM(spec_tuple, 4); + return true; +} + +/* ====== END UTILITIES ====== */ + + +/* ====== BEGIN WRITING FUNCTIONS ====== */ + +/* --- LOW-LEVEL WRITING FUNCTIONS --- */ + +static void writeByte(PyObject* outbuf, int8_t val) { + int8_t net = val; + PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int8_t)); +} + +static void writeI16(PyObject* outbuf, int16_t val) { + int16_t net = (int16_t)htons(val); + PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int16_t)); +} + +static void writeI32(PyObject* outbuf, int32_t val) { + int32_t net = (int32_t)htonl(val); + PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int32_t)); +} + +static void writeI64(PyObject* outbuf, int64_t val) { + int64_t net = (int64_t)htonll(val); + PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int64_t)); +} + +static void writeDouble(PyObject* outbuf, double dub) { + // Unfortunately, bitwise_cast doesn't work in C. Bad C! + union { + double f; + int64_t t; + } transfer; + transfer.f = dub; + writeI64(outbuf, transfer.t); +} + + +/* --- MAIN RECURSIVE OUTPUT FUCNTION -- */ + +static int +output_val(PyObject* output, PyObject* value, TType type, PyObject* typeargs) { + /* + * Refcounting Strategy: + * + * We assume that elements of the thrift_spec tuple are not going to be + * mutated, so we don't ref count those at all. Other than that, we try to + * keep a reference to all the user-created objects while we work with them. + * output_val assumes that a reference is already held. The *caller* is + * responsible for handling references + */ + + switch (type) { + + case T_BOOL: { + int v = PyObject_IsTrue(value); + if (v == -1) { + return false; + } + + writeByte(output, (int8_t) v); + break; + } + case T_I08: { + int32_t val; + + if (!parse_pyint(value, &val, INT8_MIN, INT8_MAX)) { + return false; + } + + writeByte(output, (int8_t) val); + break; + } + case T_I16: { + int32_t val; + + if (!parse_pyint(value, &val, INT16_MIN, INT16_MAX)) { + return false; + } + + writeI16(output, (int16_t) val); + break; + } + case T_I32: { + int32_t val; + + if (!parse_pyint(value, &val, INT32_MIN, INT32_MAX)) { + return false; + } + + writeI32(output, val); + break; + } + case T_I64: { + int64_t nval = PyLong_AsLongLong(value); + + if (INT_CONV_ERROR_OCCURRED(nval)) { + return false; + } + + if (!CHECK_RANGE(nval, INT64_MIN, INT64_MAX)) { + PyErr_SetString(PyExc_OverflowError, "int out of range"); + return false; + } + + writeI64(output, nval); + break; + } + + case T_DOUBLE: { + double nval = PyFloat_AsDouble(value); + if (nval == -1.0 && PyErr_Occurred()) { + return false; + } + + writeDouble(output, nval); + break; + } + + case T_STRING: { + Py_ssize_t len = PyString_Size(value); + + if (!check_ssize_t_32(len)) { + return false; + } + + writeI32(output, (int32_t) len); + PycStringIO->cwrite(output, PyString_AsString(value), (int32_t) len); + break; + } + + case T_LIST: + case T_SET: { + Py_ssize_t len; + SetListTypeArgs parsedargs; + PyObject *item; + PyObject *iterator; + + if (!parse_set_list_args(&parsedargs, typeargs)) { + return false; + } + + len = PyObject_Length(value); + + if (!check_ssize_t_32(len)) { + return false; + } + + writeByte(output, parsedargs.element_type); + writeI32(output, (int32_t) len); + + iterator = PyObject_GetIter(value); + if (iterator == NULL) { + return false; + } + + while ((item = PyIter_Next(iterator))) { + if (!output_val(output, item, parsedargs.element_type, parsedargs.typeargs)) { + Py_DECREF(item); + Py_DECREF(iterator); + return false; + } + Py_DECREF(item); + } + + Py_DECREF(iterator); + + if (PyErr_Occurred()) { + return false; + } + + break; + } + + case T_MAP: { + PyObject *k, *v; + Py_ssize_t pos = 0; + Py_ssize_t len; + + MapTypeArgs parsedargs; + + len = PyDict_Size(value); + if (!check_ssize_t_32(len)) { + return false; + } + + if (!parse_map_args(&parsedargs, typeargs)) { + return false; + } + + writeByte(output, parsedargs.ktag); + writeByte(output, parsedargs.vtag); + writeI32(output, len); + + // TODO(bmaurer): should support any mapping, not just dicts + while (PyDict_Next(value, &pos, &k, &v)) { + // TODO(dreiss): Think hard about whether these INCREFs actually + // turn any unsafe scenarios into safe scenarios. + Py_INCREF(k); + Py_INCREF(v); + + if (!output_val(output, k, parsedargs.ktag, parsedargs.ktypeargs) + || !output_val(output, v, parsedargs.vtag, parsedargs.vtypeargs)) { + Py_DECREF(k); + Py_DECREF(v); + return false; + } + Py_DECREF(k); + Py_DECREF(v); + } + break; + } + + // TODO(dreiss): Consider breaking this out as a function + // the way we did for decode_struct. + case T_STRUCT: { + StructTypeArgs parsedargs; + Py_ssize_t nspec; + Py_ssize_t i; + + if (!parse_struct_args(&parsedargs, typeargs)) { + return false; + } + + nspec = PyTuple_Size(parsedargs.spec); + + if (nspec == -1) { + return false; + } + + for (i = 0; i < nspec; i++) { + StructItemSpec parsedspec; + PyObject* spec_tuple; + PyObject* instval = NULL; + + spec_tuple = PyTuple_GET_ITEM(parsedargs.spec, i); + if (spec_tuple == Py_None) { + continue; + } + + if (!parse_struct_item_spec (&parsedspec, spec_tuple)) { + return false; + } + + instval = PyObject_GetAttr(value, parsedspec.attrname); + + if (!instval) { + return false; + } + + if (instval == Py_None) { + Py_DECREF(instval); + continue; + } + + writeByte(output, (int8_t) parsedspec.type); + writeI16(output, parsedspec.tag); + + if (!output_val(output, instval, parsedspec.type, parsedspec.typeargs)) { + Py_DECREF(instval); + return false; + } + + Py_DECREF(instval); + } + + writeByte(output, (int8_t)T_STOP); + break; + } + + case T_STOP: + case T_VOID: + case T_UTF16: + case T_UTF8: + case T_U64: + default: + PyErr_SetString(PyExc_TypeError, "Unexpected TType"); + return false; + + } + + return true; +} + + +/* --- TOP-LEVEL WRAPPER FOR OUTPUT -- */ + +static PyObject * +encode_binary(PyObject *self, PyObject *args) { + PyObject* enc_obj; + PyObject* type_args; + PyObject* buf; + PyObject* ret = NULL; + + if (!PyArg_ParseTuple(args, "OO", &enc_obj, &type_args)) { + return NULL; + } + + buf = PycStringIO->NewOutput(INIT_OUTBUF_SIZE); + if (output_val(buf, enc_obj, T_STRUCT, type_args)) { + ret = PycStringIO->cgetvalue(buf); + } + + Py_DECREF(buf); + return ret; +} + +/* ====== END WRITING FUNCTIONS ====== */ + + +/* ====== BEGIN READING FUNCTIONS ====== */ + +/* --- LOW-LEVEL READING FUNCTIONS --- */ + +static void +free_decodebuf(DecodeBuffer* d) { + Py_XDECREF(d->stringiobuf); + Py_XDECREF(d->refill_callable); +} + +static bool +decode_buffer_from_obj(DecodeBuffer* dest, PyObject* obj) { + dest->stringiobuf = PyObject_GetAttr(obj, INTERN_STRING(cstringio_buf)); + if (!dest->stringiobuf) { + return false; + } + + if (!PycStringIO_InputCheck(dest->stringiobuf)) { + free_decodebuf(dest); + PyErr_SetString(PyExc_TypeError, "expecting stringio input"); + return false; + } + + dest->refill_callable = PyObject_GetAttr(obj, INTERN_STRING(cstringio_refill)); + + if(!dest->refill_callable) { + free_decodebuf(dest); + return false; + } + + if (!PyCallable_Check(dest->refill_callable)) { + free_decodebuf(dest); + PyErr_SetString(PyExc_TypeError, "expecting callable"); + return false; + } + + return true; +} + +static bool readBytes(DecodeBuffer* input, char** output, int len) { + int read; + + // TODO(dreiss): Don't fear the malloc. Think about taking a copy of + // the partial read instead of forcing the transport + // to prepend it to its buffer. + + read = PycStringIO->cread(input->stringiobuf, output, len); + + if (read == len) { + return true; + } else if (read == -1) { + return false; + } else { + PyObject* newiobuf; + + // using building functions as this is a rare codepath + newiobuf = PyObject_CallFunction( + input->refill_callable, "s#i", *output, read, len, NULL); + if (newiobuf == NULL) { + return false; + } + + // must do this *AFTER* the call so that we don't deref the io buffer + Py_CLEAR(input->stringiobuf); + input->stringiobuf = newiobuf; + + read = PycStringIO->cread(input->stringiobuf, output, len); + + if (read == len) { + return true; + } else if (read == -1) { + return false; + } else { + // TODO(dreiss): This could be a valid code path for big binary blobs. + PyErr_SetString(PyExc_TypeError, + "refill claimed to have refilled the buffer, but didn't!!"); + return false; + } + } +} + +static int8_t readByte(DecodeBuffer* input) { + char* buf; + if (!readBytes(input, &buf, sizeof(int8_t))) { + return -1; + } + + return *(int8_t*) buf; +} + +static int16_t readI16(DecodeBuffer* input) { + char* buf; + if (!readBytes(input, &buf, sizeof(int16_t))) { + return -1; + } + + return (int16_t) ntohs(*(int16_t*) buf); +} + +static int32_t readI32(DecodeBuffer* input) { + char* buf; + if (!readBytes(input, &buf, sizeof(int32_t))) { + return -1; + } + return (int32_t) ntohl(*(int32_t*) buf); +} + + +static int64_t readI64(DecodeBuffer* input) { + char* buf; + if (!readBytes(input, &buf, sizeof(int64_t))) { + return -1; + } + + return (int64_t) ntohll(*(int64_t*) buf); +} + +static double readDouble(DecodeBuffer* input) { + union { + int64_t f; + double t; + } transfer; + + transfer.f = readI64(input); + if (transfer.f == -1) { + return -1; + } + return transfer.t; +} + +static bool +checkTypeByte(DecodeBuffer* input, TType expected) { + TType got = readByte(input); + if (INT_CONV_ERROR_OCCURRED(got)) { + return false; + } + + if (expected != got) { + PyErr_SetString(PyExc_TypeError, "got wrong ttype while reading field"); + return false; + } + return true; +} + +static bool +skip(DecodeBuffer* input, TType type) { +#define SKIPBYTES(n) \ + do { \ + if (!readBytes(input, &dummy_buf, (n))) { \ + return false; \ + } \ + } while(0) + + char* dummy_buf; + + switch (type) { + + case T_BOOL: + case T_I08: SKIPBYTES(1); break; + case T_I16: SKIPBYTES(2); break; + case T_I32: SKIPBYTES(4); break; + case T_I64: + case T_DOUBLE: SKIPBYTES(8); break; + + case T_STRING: { + // TODO(dreiss): Find out if these check_ssize_t32s are really necessary. + int len = readI32(input); + if (!check_ssize_t_32(len)) { + return false; + } + SKIPBYTES(len); + break; + } + + case T_LIST: + case T_SET: { + TType etype; + int len, i; + + etype = readByte(input); + if (etype == -1) { + return false; + } + + len = readI32(input); + if (!check_ssize_t_32(len)) { + return false; + } + + for (i = 0; i < len; i++) { + if (!skip(input, etype)) { + return false; + } + } + break; + } + + case T_MAP: { + TType ktype, vtype; + int len, i; + + ktype = readByte(input); + if (ktype == -1) { + return false; + } + + vtype = readByte(input); + if (vtype == -1) { + return false; + } + + len = readI32(input); + if (!check_ssize_t_32(len)) { + return false; + } + + for (i = 0; i < len; i++) { + if (!(skip(input, ktype) && skip(input, vtype))) { + return false; + } + } + break; + } + + case T_STRUCT: { + while (true) { + TType type; + + type = readByte(input); + if (type == -1) { + return false; + } + + if (type == T_STOP) + break; + + SKIPBYTES(2); // tag + if (!skip(input, type)) { + return false; + } + } + break; + } + + case T_STOP: + case T_VOID: + case T_UTF16: + case T_UTF8: + case T_U64: + default: + PyErr_SetString(PyExc_TypeError, "Unexpected TType"); + return false; + + } + + return true; + +#undef SKIPBYTES +} + + +/* --- HELPER FUNCTION FOR DECODE_VAL --- */ + +static PyObject* +decode_val(DecodeBuffer* input, TType type, PyObject* typeargs); + +static bool +decode_struct(DecodeBuffer* input, PyObject* output, PyObject* spec_seq) { + int spec_seq_len = PyTuple_Size(spec_seq); + if (spec_seq_len == -1) { + return false; + } + + while (true) { + TType type; + int16_t tag; + PyObject* item_spec; + PyObject* fieldval = NULL; + StructItemSpec parsedspec; + + type = readByte(input); + if (type == -1) { + return false; + } + if (type == T_STOP) { + break; + } + tag = readI16(input); + if (INT_CONV_ERROR_OCCURRED(tag)) { + return false; + } + if (tag >= 0 && tag < spec_seq_len) { + item_spec = PyTuple_GET_ITEM(spec_seq, tag); + } else { + item_spec = Py_None; + } + + if (item_spec == Py_None) { + if (!skip(input, type)) { + return false; + } else { + continue; + } + } + + if (!parse_struct_item_spec(&parsedspec, item_spec)) { + return false; + } + if (parsedspec.type != type) { + if (!skip(input, type)) { + PyErr_SetString(PyExc_TypeError, "struct field had wrong type while reading and can't be skipped"); + return false; + } else { + continue; + } + } + + fieldval = decode_val(input, parsedspec.type, parsedspec.typeargs); + if (fieldval == NULL) { + return false; + } + + if (PyObject_SetAttr(output, parsedspec.attrname, fieldval) == -1) { + Py_DECREF(fieldval); + return false; + } + Py_DECREF(fieldval); + } + return true; +} + + +/* --- MAIN RECURSIVE INPUT FUCNTION --- */ + +// Returns a new reference. +static PyObject* +decode_val(DecodeBuffer* input, TType type, PyObject* typeargs) { + switch (type) { + + case T_BOOL: { + int8_t v = readByte(input); + if (INT_CONV_ERROR_OCCURRED(v)) { + return NULL; + } + + switch (v) { + case 0: Py_RETURN_FALSE; + case 1: Py_RETURN_TRUE; + // Don't laugh. This is a potentially serious issue. + default: PyErr_SetString(PyExc_TypeError, "boolean out of range"); return NULL; + } + break; + } + case T_I08: { + int8_t v = readByte(input); + if (INT_CONV_ERROR_OCCURRED(v)) { + return NULL; + } + + return PyInt_FromLong(v); + } + case T_I16: { + int16_t v = readI16(input); + if (INT_CONV_ERROR_OCCURRED(v)) { + return NULL; + } + return PyInt_FromLong(v); + } + case T_I32: { + int32_t v = readI32(input); + if (INT_CONV_ERROR_OCCURRED(v)) { + return NULL; + } + return PyInt_FromLong(v); + } + + case T_I64: { + int64_t v = readI64(input); + if (INT_CONV_ERROR_OCCURRED(v)) { + return NULL; + } + // TODO(dreiss): Find out if we can take this fastpath always when + // sizeof(long) == sizeof(long long). + if (CHECK_RANGE(v, LONG_MIN, LONG_MAX)) { + return PyInt_FromLong((long) v); + } + + return PyLong_FromLongLong(v); + } + + case T_DOUBLE: { + double v = readDouble(input); + if (v == -1.0 && PyErr_Occurred()) { + return false; + } + return PyFloat_FromDouble(v); + } + + case T_STRING: { + Py_ssize_t len = readI32(input); + char* buf; + if (!readBytes(input, &buf, len)) { + return NULL; + } + + return PyString_FromStringAndSize(buf, len); + } + + case T_LIST: + case T_SET: { + SetListTypeArgs parsedargs; + int32_t len; + PyObject* ret = NULL; + int i; + + if (!parse_set_list_args(&parsedargs, typeargs)) { + return NULL; + } + + if (!checkTypeByte(input, parsedargs.element_type)) { + return NULL; + } + + len = readI32(input); + if (!check_ssize_t_32(len)) { + return NULL; + } + + ret = PyList_New(len); + if (!ret) { + return NULL; + } + + for (i = 0; i < len; i++) { + PyObject* item = decode_val(input, parsedargs.element_type, parsedargs.typeargs); + if (!item) { + Py_DECREF(ret); + return NULL; + } + PyList_SET_ITEM(ret, i, item); + } + + // TODO(dreiss): Consider biting the bullet and making two separate cases + // for list and set, avoiding this post facto conversion. + if (type == T_SET) { + PyObject* setret; +#if (PY_VERSION_HEX < 0x02050000) + // hack needed for older versions + setret = PyObject_CallFunctionObjArgs((PyObject*)&PySet_Type, ret, NULL); +#else + // official version + setret = PySet_New(ret); +#endif + Py_DECREF(ret); + return setret; + } + return ret; + } + + case T_MAP: { + int32_t len; + int i; + MapTypeArgs parsedargs; + PyObject* ret = NULL; + + if (!parse_map_args(&parsedargs, typeargs)) { + return NULL; + } + + if (!checkTypeByte(input, parsedargs.ktag)) { + return NULL; + } + if (!checkTypeByte(input, parsedargs.vtag)) { + return NULL; + } + + len = readI32(input); + if (!check_ssize_t_32(len)) { + return false; + } + + ret = PyDict_New(); + if (!ret) { + goto error; + } + + for (i = 0; i < len; i++) { + PyObject* k = NULL; + PyObject* v = NULL; + k = decode_val(input, parsedargs.ktag, parsedargs.ktypeargs); + if (k == NULL) { + goto loop_error; + } + v = decode_val(input, parsedargs.vtag, parsedargs.vtypeargs); + if (v == NULL) { + goto loop_error; + } + if (PyDict_SetItem(ret, k, v) == -1) { + goto loop_error; + } + + Py_DECREF(k); + Py_DECREF(v); + continue; + + // Yuck! Destructors, anyone? + loop_error: + Py_XDECREF(k); + Py_XDECREF(v); + goto error; + } + + return ret; + + error: + Py_XDECREF(ret); + return NULL; + } + + case T_STRUCT: { + StructTypeArgs parsedargs; + PyObject* ret; + if (!parse_struct_args(&parsedargs, typeargs)) { + return NULL; + } + + ret = PyObject_CallObject(parsedargs.klass, NULL); + if (!ret) { + return NULL; + } + + if (!decode_struct(input, ret, parsedargs.spec)) { + Py_DECREF(ret); + return NULL; + } + + return ret; + } + + case T_STOP: + case T_VOID: + case T_UTF16: + case T_UTF8: + case T_U64: + default: + PyErr_SetString(PyExc_TypeError, "Unexpected TType"); + return NULL; + } +} + + +/* --- TOP-LEVEL WRAPPER FOR INPUT -- */ + +static PyObject* +decode_binary(PyObject *self, PyObject *args) { + PyObject* output_obj = NULL; + PyObject* transport = NULL; + PyObject* typeargs = NULL; + StructTypeArgs parsedargs; + DecodeBuffer input = {0, 0}; + + if (!PyArg_ParseTuple(args, "OOO", &output_obj, &transport, &typeargs)) { + return NULL; + } + + if (!parse_struct_args(&parsedargs, typeargs)) { + return NULL; + } + + if (!decode_buffer_from_obj(&input, transport)) { + return NULL; + } + + if (!decode_struct(&input, output_obj, parsedargs.spec)) { + free_decodebuf(&input); + return NULL; + } + + free_decodebuf(&input); + + Py_RETURN_NONE; +} + +/* ====== END READING FUNCTIONS ====== */ + + +/* -- PYTHON MODULE SETUP STUFF --- */ + +static PyMethodDef ThriftFastBinaryMethods[] = { + + {"encode_binary", encode_binary, METH_VARARGS, ""}, + {"decode_binary", decode_binary, METH_VARARGS, ""}, + + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC +initfastbinary(void) { +#define INIT_INTERN_STRING(value) \ + do { \ + INTERN_STRING(value) = PyString_InternFromString(#value); \ + if(!INTERN_STRING(value)) return; \ + } while(0) + + INIT_INTERN_STRING(cstringio_buf); + INIT_INTERN_STRING(cstringio_refill); +#undef INIT_INTERN_STRING + + PycString_IMPORT; + if (PycStringIO == NULL) return; + + (void) Py_InitModule("thrift.protocol.fastbinary", ThriftFastBinaryMethods); +} diff --git a/module/lib/thrift/server/THttpServer.py b/module/lib/thrift/server/THttpServer.py index 3047d9c00..be54bab94 100644 --- a/module/lib/thrift/server/THttpServer.py +++ b/module/lib/thrift/server/THttpServer.py @@ -22,6 +22,7 @@ import BaseHTTPServer from thrift.server import TServer from thrift.transport import TTransport + class ResponseException(Exception): """Allows handlers to override the HTTP response @@ -39,16 +40,19 @@ class THttpServer(TServer.TServer): """A simple HTTP-based Thrift server This class is not very performant, but it is useful (for example) for - acting as a mock version of an Apache-based PHP Thrift endpoint.""" - - def __init__(self, processor, server_address, - inputProtocolFactory, outputProtocolFactory = None, - server_class = BaseHTTPServer.HTTPServer): + acting as a mock version of an Apache-based PHP Thrift endpoint. + """ + def __init__(self, + processor, + server_address, + inputProtocolFactory, + outputProtocolFactory=None, + server_class=BaseHTTPServer.HTTPServer): """Set up protocol factories and HTTP server. See BaseHTTPServer for server_address. - See TServer for protocol factories.""" - + See TServer for protocol factories. + """ if outputProtocolFactory is None: outputProtocolFactory = inputProtocolFactory @@ -62,7 +66,8 @@ class THttpServer(TServer.TServer): # Don't care about the request path. itrans = TTransport.TFileObjectTransport(self.rfile) otrans = TTransport.TFileObjectTransport(self.wfile) - itrans = TTransport.TBufferedTransport(itrans, int(self.headers['Content-Length'])) + itrans = TTransport.TBufferedTransport( + itrans, int(self.headers['Content-Length'])) otrans = TTransport.TMemoryBuffer() iprot = thttpserver.inputProtocolFactory.getProtocol(itrans) oprot = thttpserver.outputProtocolFactory.getProtocol(otrans) diff --git a/module/lib/thrift/server/TNonblockingServer.py b/module/lib/thrift/server/TNonblockingServer.py index ea348a0b6..fa478d01f 100644 --- a/module/lib/thrift/server/TNonblockingServer.py +++ b/module/lib/thrift/server/TNonblockingServer.py @@ -18,10 +18,11 @@ # """Implementation of non-blocking server. -The main idea of the server is reciving and sending requests -only from main thread. +The main idea of the server is to receive and send requests +only from the main thread. -It also makes thread pool server in tasks terms, not connections. +The thread poool should be sized for concurrent tasks, not +maximum connections """ import threading import socket @@ -35,8 +36,10 @@ from thrift.protocol.TBinaryProtocol import TBinaryProtocolFactory __all__ = ['TNonblockingServer'] + class Worker(threading.Thread): """Worker is a small helper to process incoming connection.""" + def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue @@ -60,8 +63,9 @@ WAIT_PROCESS = 2 SEND_ANSWER = 3 CLOSED = 4 + def locked(func): - "Decorator which locks self.lock." + """Decorator which locks self.lock.""" def nested(self, *args, **kwargs): self.lock.acquire() try: @@ -70,8 +74,9 @@ def locked(func): self.lock.release() return nested + def socket_exception(func): - "Decorator close object on socket.error." + """Decorator close object on socket.error.""" def read(self, *args, **kwargs): try: return func(self, *args, **kwargs) @@ -79,16 +84,17 @@ def socket_exception(func): self.close() return read + class Connection: """Basic class is represented connection. - + It can be in state: WAIT_LEN --- connection is reading request len. WAIT_MESSAGE --- connection is reading request. - WAIT_PROCESS --- connection has just read whole request and - waits for call ready routine. + WAIT_PROCESS --- connection has just read whole request and + waits for call ready routine. SEND_ANSWER --- connection is sending answer string (including length - of answer). + of answer). CLOSED --- socket was closed and connection should be deleted. """ def __init__(self, new_socket, wake_up): @@ -102,13 +108,13 @@ class Connection: def _read_len(self): """Reads length of request. - - It's really paranoic routine and it may be replaced by - self.socket.recv(4).""" + + It's a safer alternative to self.socket.recv(4) + """ read = self.socket.recv(4 - len(self.message)) if len(read) == 0: - # if we read 0 bytes and self.message is empty, it means client close - # connection + # if we read 0 bytes and self.message is empty, then + # the client closed the connection if len(self.message) != 0: logging.error("can't read frame size from socket") self.close() @@ -117,8 +123,8 @@ class Connection: if len(self.message) == 4: self.len, = struct.unpack('!i', self.message) if self.len < 0: - logging.error("negative frame size, it seems client"\ - " doesn't use FramedTransport") + logging.error("negative frame size, it seems client " + "doesn't use FramedTransport") self.close() elif self.len == 0: logging.error("empty frame, it's really strange") @@ -139,8 +145,8 @@ class Connection: elif self.status == WAIT_MESSAGE: read = self.socket.recv(self.len - len(self.message)) if len(read) == 0: - logging.error("can't read frame from socket (get %d of %d bytes)" % - (len(self.message), self.len)) + logging.error("can't read frame from socket (get %d of " + "%d bytes)" % (len(self.message), self.len)) self.close() return self.message += read @@ -162,14 +168,14 @@ class Connection: @locked def ready(self, all_ok, message): """Callback function for switching state and waking up main thread. - + This function is the only function witch can be called asynchronous. - + The ready can switch Connection to three states: WAIT_LEN if request was oneway. SEND_ANSWER if request was processed in normal way. CLOSED if request throws unexpected exception. - + The one wakes up main thread. """ assert self.status == WAIT_PROCESS @@ -189,33 +195,39 @@ class Connection: @locked def is_writeable(self): - "Returns True if connection should be added to write list of select." + """Return True if connection should be added to write list of select""" return self.status == SEND_ANSWER # it's not necessary, but... @locked def is_readable(self): - "Returns True if connection should be added to read list of select." + """Return True if connection should be added to read list of select""" return self.status in (WAIT_LEN, WAIT_MESSAGE) @locked def is_closed(self): - "Returns True if connection is closed." + """Returns True if connection is closed.""" return self.status == CLOSED def fileno(self): - "Returns the file descriptor of the associated socket." + """Returns the file descriptor of the associated socket.""" return self.socket.fileno() def close(self): - "Closes connection" + """Closes connection""" self.status = CLOSED self.socket.close() + class TNonblockingServer: """Non-blocking server.""" - def __init__(self, processor, lsocket, inputProtocolFactory=None, - outputProtocolFactory=None, threads=10): + + def __init__(self, + processor, + lsocket, + inputProtocolFactory=None, + outputProtocolFactory=None, + threads=10): self.processor = processor self.socket = lsocket self.in_protocol = inputProtocolFactory or TBinaryProtocolFactory() @@ -225,15 +237,18 @@ class TNonblockingServer: self.tasks = Queue.Queue() self._read, self._write = socket.socketpair() self.prepared = False + self._stop = False def setNumThreads(self, num): """Set the number of worker threads that should be created.""" # implement ThreadPool interface - assert not self.prepared, "You can't change number of threads for working server" + assert not self.prepared, "Can't change number of threads after start" self.threads = num def prepare(self): """Prepares server for serve requests.""" + if self.prepared: + return self.socket.listen() for _ in xrange(self.threads): thread = Worker(self.tasks) @@ -243,16 +258,32 @@ class TNonblockingServer: def wake_up(self): """Wake up main thread. - + The server usualy waits in select call in we should terminate one. The simplest way is using socketpair. - + Select always wait to read from the first socket of socketpair. - + In this case, we can just write anything to the second socket from - socketpair.""" + socketpair. + """ self._write.send('1') + def stop(self): + """Stop the server. + + This method causes the serve() method to return. stop() may be invoked + from within your handler, or from another thread. + + After stop() is called, serve() will return but the server will still + be listening on the socket. serve() may then be called again to resume + processing requests. Alternatively, close() may be called after + serve() returns to close the server socket and shutdown all worker + threads. + """ + self._stop = True + self.wake_up() + def _select(self): """Does select on open connections.""" readable = [self.socket.handle.fileno(), self._read.fileno()] @@ -265,21 +296,22 @@ class TNonblockingServer: if connection.is_closed(): del self.clients[i] return select.select(readable, writable, readable) - + def handle(self): """Handle requests. - - WARNING! You must call prepare BEFORE calling handle. + + WARNING! You must call prepare() BEFORE calling handle() """ assert self.prepared, "You have to call prepare before handle" rset, wset, xset = self._select() for readable in rset: if readable == self._read.fileno(): # don't care i just need to clean readable flag - self._read.recv(1024) + self._read.recv(1024) elif readable == self.socket.handle.fileno(): client = self.socket.accept().handle - self.clients[client.fileno()] = Connection(client, self.wake_up) + self.clients[client.fileno()] = Connection(client, + self.wake_up) else: connection = self.clients[readable] connection.read() @@ -288,7 +320,7 @@ class TNonblockingServer: otransport = TTransport.TMemoryBuffer() iprot = self.in_protocol.getProtocol(itransport) oprot = self.out_protocol.getProtocol(otransport) - self.tasks.put([self.processor, iprot, oprot, + self.tasks.put([self.processor, iprot, oprot, otransport, connection.ready]) for writeable in wset: self.clients[writeable].write() @@ -302,9 +334,13 @@ class TNonblockingServer: self.tasks.put([None, None, None, None, None]) self.socket.close() self.prepared = False - + def serve(self): - """Serve forever.""" + """Serve requests. + + Serve requests forever, or until stop() is called. + """ + self._stop = False self.prepare() - while True: + while not self._stop: self.handle() diff --git a/module/lib/thrift/server/TProcessPoolServer.py b/module/lib/thrift/server/TProcessPoolServer.py index 7ed814a88..7a695a883 100644 --- a/module/lib/thrift/server/TProcessPoolServer.py +++ b/module/lib/thrift/server/TProcessPoolServer.py @@ -24,15 +24,14 @@ from multiprocessing import Process, Value, Condition, reduction from TServer import TServer from thrift.transport.TTransport import TTransportException + class TProcessPoolServer(TServer): + """Server with a fixed size pool of worker subprocesses to service requests - """ - Server with a fixed size pool of worker subprocesses which service requests. Note that if you need shared state between the handlers - it's up to you! Written by Dvir Volk, doat.com """ - - def __init__(self, * args): + def __init__(self, *args): TServer.__init__(self, *args) self.numWorkers = 10 self.workers = [] @@ -50,12 +49,11 @@ class TProcessPoolServer(TServer): self.numWorkers = num def workerProcess(self): - """Loop around getting clients from the shared queue and process them.""" - + """Loop getting clients from the shared queue and process them""" if self.postForkCallback: self.postForkCallback() - while self.isRunning.value == True: + while self.isRunning.value: try: client = self.serverTransport.accept() self.serveClient(client) @@ -82,17 +80,15 @@ class TProcessPoolServer(TServer): itrans.close() otrans.close() - def serve(self): - """Start a fixed number of worker threads and put client into a queue""" - - #this is a shared state that can tell the workers to exit when set as false + """Start workers and put into queue""" + # this is a shared state that can tell the workers to exit when False self.isRunning.value = True - #first bind and listen to the port + # first bind and listen to the port self.serverTransport.listen() - #fork the children + # fork the children for i in range(self.numWorkers): try: w = Process(target=self.workerProcess) @@ -102,16 +98,14 @@ class TProcessPoolServer(TServer): except Exception, x: logging.exception(x) - #wait until the condition is set by stop() - + # wait until the condition is set by stop() while True: - self.stopCondition.acquire() try: self.stopCondition.wait() break except (SystemExit, KeyboardInterrupt): - break + break except Exception, x: logging.exception(x) @@ -122,4 +116,3 @@ class TProcessPoolServer(TServer): self.stopCondition.acquire() self.stopCondition.notify() self.stopCondition.release() - diff --git a/module/lib/thrift/server/TServer.py b/module/lib/thrift/server/TServer.py index 8456e2d40..2f24842c4 100644 --- a/module/lib/thrift/server/TServer.py +++ b/module/lib/thrift/server/TServer.py @@ -17,27 +17,28 @@ # under the License. # +import Queue import logging -import sys import os -import traceback +import sys import threading -import Queue +import traceback from thrift.Thrift import TProcessor -from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol +from thrift.transport import TTransport -class TServer: - """Base interface for a server, which must have a serve method.""" +class TServer: + """Base interface for a server, which must have a serve() method. - """ 3 constructors for all servers: + Three constructors for all servers: 1) (processor, serverTransport) 2) (processor, serverTransport, transportFactory, protocolFactory) 3) (processor, serverTransport, inputTransportFactory, outputTransportFactory, - inputProtocolFactory, outputProtocolFactory)""" + inputProtocolFactory, outputProtocolFactory) + """ def __init__(self, *args): if (len(args) == 2): self.__initArgs__(args[0], args[1], @@ -63,8 +64,8 @@ class TServer: def serve(self): pass -class TSimpleServer(TServer): +class TSimpleServer(TServer): """Simple single-threaded server that just pumps around one transport.""" def __init__(self, *args): @@ -89,8 +90,8 @@ class TSimpleServer(TServer): itrans.close() otrans.close() -class TThreadedServer(TServer): +class TThreadedServer(TServer): """Threaded server that spawns a new thread per each connection.""" def __init__(self, *args, **kwargs): @@ -102,7 +103,7 @@ class TThreadedServer(TServer): while True: try: client = self.serverTransport.accept() - t = threading.Thread(target = self.handle, args=(client,)) + t = threading.Thread(target=self.handle, args=(client,)) t.setDaemon(self.daemon) t.start() except KeyboardInterrupt: @@ -126,8 +127,8 @@ class TThreadedServer(TServer): itrans.close() otrans.close() -class TThreadPoolServer(TServer): +class TThreadPoolServer(TServer): """Server with a fixed size pool of threads which service requests.""" def __init__(self, *args, **kwargs): @@ -170,7 +171,7 @@ class TThreadPoolServer(TServer): """Start a fixed number of worker threads and put client into a queue""" for i in range(self.threads): try: - t = threading.Thread(target = self.serveThread) + t = threading.Thread(target=self.serveThread) t.setDaemon(self.daemon) t.start() except Exception, x: @@ -187,9 +188,8 @@ class TThreadPoolServer(TServer): class TForkingServer(TServer): + """A Thrift server that forks a new process for each request - """A Thrift server that forks a new process for each request""" - """ This is more scalable than the threaded server as it does not cause GIL contention. @@ -200,7 +200,6 @@ class TForkingServer(TServer): This code is heavily inspired by SocketServer.ForkingMixIn in the Python stdlib. """ - def __init__(self, *args): TServer.__init__(self, *args) self.children = [] @@ -212,14 +211,13 @@ class TForkingServer(TServer): except IOError, e: logging.warning(e, exc_info=True) - self.serverTransport.listen() while True: client = self.serverTransport.accept() try: pid = os.fork() - if pid: # parent + if pid: # parent # add before collect, otherwise you race w/ waitpid self.children.append(pid) self.collect_children() @@ -258,7 +256,6 @@ class TForkingServer(TServer): except Exception, x: logging.exception(x) - def collect_children(self): while self.children: try: @@ -270,5 +267,3 @@ class TForkingServer(TServer): self.children.remove(pid) else: break - - diff --git a/module/lib/thrift/transport/THttpClient.py b/module/lib/thrift/transport/THttpClient.py index 50269785c..ea80a1ae8 100644 --- a/module/lib/thrift/transport/THttpClient.py +++ b/module/lib/thrift/transport/THttpClient.py @@ -17,16 +17,20 @@ # under the License. # -from TTransport import * -from cStringIO import StringIO - -import urlparse import httplib -import warnings +import os import socket +import sys +import urllib +import urlparse +import warnings -class THttpClient(TTransportBase): +from cStringIO import StringIO +from TTransport import * + + +class THttpClient(TTransportBase): """Http implementation of TTransport base.""" def __init__(self, uri_or_host, port=None, path=None): @@ -35,10 +39,13 @@ class THttpClient(TTransportBase): THttpClient(host, port, path) - deprecated THttpClient(uri) - Only the second supports https.""" - + Only the second supports https. + """ if port is not None: - warnings.warn("Please use the THttpClient('http://host:port/path') syntax", DeprecationWarning, stacklevel=2) + warnings.warn( + "Please use the THttpClient('http://host:port/path') syntax", + DeprecationWarning, + stacklevel=2) self.host = uri_or_host self.port = port assert path @@ -59,6 +66,7 @@ class THttpClient(TTransportBase): self.__wbuf = StringIO() self.__http = None self.__timeout = None + self.__custom_headers = None def open(self): if self.scheme == 'http': @@ -71,7 +79,7 @@ class THttpClient(TTransportBase): self.__http = None def isOpen(self): - return self.__http != None + return self.__http is not None def setTimeout(self, ms): if not hasattr(socket, 'getdefaulttimeout'): @@ -80,7 +88,10 @@ class THttpClient(TTransportBase): if ms is None: self.__timeout = None else: - self.__timeout = ms/1000.0 + self.__timeout = ms / 1000.0 + + def setCustomHeaders(self, headers): + self.__custom_headers = headers def read(self, sz): return self.__http.file.read(sz) @@ -100,7 +111,7 @@ class THttpClient(TTransportBase): def flush(self): if self.isOpen(): self.close() - self.open(); + self.open() # Pull data out of buffer data = self.__wbuf.getvalue() @@ -113,6 +124,18 @@ class THttpClient(TTransportBase): self.__http.putheader('Host', self.host) self.__http.putheader('Content-Type', 'application/x-thrift') self.__http.putheader('Content-Length', str(len(data))) + + if not self.__custom_headers or 'User-Agent' not in self.__custom_headers: + user_agent = 'Python/THttpClient' + script = os.path.basename(sys.argv[0]) + if script: + user_agent = '%s (%s)' % (user_agent, urllib.quote(script)) + self.__http.putheader('User-Agent', user_agent) + + if self.__custom_headers: + for key, val in self.__custom_headers.iteritems(): + self.__http.putheader(key, val) + self.__http.endheaders() # Write payload diff --git a/module/lib/thrift/transport/TSSLSocket.py b/module/lib/thrift/transport/TSSLSocket.py new file mode 100644 index 000000000..81e098426 --- /dev/null +++ b/module/lib/thrift/transport/TSSLSocket.py @@ -0,0 +1,214 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import os +import socket +import ssl + +from thrift.transport import TSocket +from thrift.transport.TTransport import TTransportException + + +class TSSLSocket(TSocket.TSocket): + """ + SSL implementation of client-side TSocket + + This class creates outbound sockets wrapped using the + python standard ssl module for encrypted connections. + + The protocol used is set using the class variable + SSL_VERSION, which must be one of ssl.PROTOCOL_* and + defaults to ssl.PROTOCOL_TLSv1 for greatest security. + """ + SSL_VERSION = ssl.PROTOCOL_TLSv1 + + def __init__(self, + host='localhost', + port=9090, + validate=True, + ca_certs=None, + keyfile=None, + certfile=None, + unix_socket=None): + """Create SSL TSocket + + @param validate: Set to False to disable SSL certificate validation + @type validate: bool + @param ca_certs: Filename to the Certificate Authority pem file, possibly a + file downloaded from: http://curl.haxx.se/ca/cacert.pem This is passed to + the ssl_wrap function as the 'ca_certs' parameter. + @type ca_certs: str + @param keyfile: The private key + @type keyfile: str + @param certfile: The cert file + @type certfile: str + + Raises an IOError exception if validate is True and the ca_certs file is + None, not present or unreadable. + """ + self.validate = validate + self.is_valid = False + self.peercert = None + if not validate: + self.cert_reqs = ssl.CERT_NONE + else: + self.cert_reqs = ssl.CERT_REQUIRED + self.ca_certs = ca_certs + self.keyfile = keyfile + self.certfile = certfile + if validate: + if ca_certs is None or not os.access(ca_certs, os.R_OK): + raise IOError('Certificate Authority ca_certs file "%s" ' + 'is not readable, cannot validate SSL ' + 'certificates.' % (ca_certs)) + TSocket.TSocket.__init__(self, host, port, unix_socket) + + def open(self): + try: + res0 = self._resolveAddr() + for res in res0: + sock_family, sock_type = res[0:2] + ip_port = res[4] + plain_sock = socket.socket(sock_family, sock_type) + self.handle = ssl.wrap_socket(plain_sock, + ssl_version=self.SSL_VERSION, + do_handshake_on_connect=True, + ca_certs=self.ca_certs, + keyfile=self.keyfile, + certfile=self.certfile, + cert_reqs=self.cert_reqs) + self.handle.settimeout(self._timeout) + try: + self.handle.connect(ip_port) + except socket.error, e: + if res is not res0[-1]: + continue + else: + raise e + break + except socket.error, e: + if self._unix_socket: + message = 'Could not connect to secure socket %s: %s' \ + % (self._unix_socket, e) + else: + message = 'Could not connect to %s:%d: %s' % (self.host, self.port, e) + raise TTransportException(type=TTransportException.NOT_OPEN, + message=message) + if self.validate: + self._validate_cert() + + def _validate_cert(self): + """internal method to validate the peer's SSL certificate, and to check the + commonName of the certificate to ensure it matches the hostname we + used to make this connection. Does not support subjectAltName records + in certificates. + + raises TTransportException if the certificate fails validation. + """ + cert = self.handle.getpeercert() + self.peercert = cert + if 'subject' not in cert: + raise TTransportException( + type=TTransportException.NOT_OPEN, + message='No SSL certificate found from %s:%s' % (self.host, self.port)) + fields = cert['subject'] + for field in fields: + # ensure structure we get back is what we expect + if not isinstance(field, tuple): + continue + cert_pair = field[0] + if len(cert_pair) < 2: + continue + cert_key, cert_value = cert_pair[0:2] + if cert_key != 'commonName': + continue + certhost = cert_value + # this check should be performed by some sort of Access Manager + if certhost == self.host: + # success, cert commonName matches desired hostname + self.is_valid = True + return + else: + raise TTransportException( + type=TTransportException.UNKNOWN, + message='Hostname we connected to "%s" doesn\'t match certificate ' + 'provided commonName "%s"' % (self.host, certhost)) + raise TTransportException( + type=TTransportException.UNKNOWN, + message='Could not validate SSL certificate from ' + 'host "%s". Cert=%s' % (self.host, cert)) + + +class TSSLServerSocket(TSocket.TServerSocket): + """SSL implementation of TServerSocket + + This uses the ssl module's wrap_socket() method to provide SSL + negotiated encryption. + """ + SSL_VERSION = ssl.PROTOCOL_TLSv1 + + def __init__(self, + host=None, + port=9090, + certfile='cert.pem', + unix_socket=None): + """Initialize a TSSLServerSocket + + @param certfile: filename of the server certificate, defaults to cert.pem + @type certfile: str + @param host: The hostname or IP to bind the listen socket to, + i.e. 'localhost' for only allowing local network connections. + Pass None to bind to all interfaces. + @type host: str + @param port: The port to listen on for inbound connections. + @type port: int + """ + self.setCertfile(certfile) + TSocket.TServerSocket.__init__(self, host, port) + + def setCertfile(self, certfile): + """Set or change the server certificate file used to wrap new connections. + + @param certfile: The filename of the server certificate, + i.e. '/etc/certs/server.pem' + @type certfile: str + + Raises an IOError exception if the certfile is not present or unreadable. + """ + if not os.access(certfile, os.R_OK): + raise IOError('No such certfile found: %s' % (certfile)) + self.certfile = certfile + + def accept(self): + plain_client, addr = self.handle.accept() + try: + client = ssl.wrap_socket(plain_client, certfile=self.certfile, + server_side=True, ssl_version=self.SSL_VERSION) + except ssl.SSLError, ssl_exc: + # failed handshake/ssl wrap, close socket to client + plain_client.close() + # raise ssl_exc + # We can't raise the exception, because it kills most TServer derived + # serve() methods. + # Instead, return None, and let the TServer instance deal with it in + # other exception handling. (but TSimpleServer dies anyway) + return None + result = TSocket.TSocket() + result.setHandle(client) + return result diff --git a/module/lib/thrift/transport/TSocket.py b/module/lib/thrift/transport/TSocket.py index 4e0e1874f..9e2b3849b 100644 --- a/module/lib/thrift/transport/TSocket.py +++ b/module/lib/thrift/transport/TSocket.py @@ -17,24 +17,33 @@ # under the License. # -from TTransport import * -import os import errno +import os import socket import sys +from TTransport import * + + class TSocketBase(TTransportBase): def _resolveAddr(self): if self._unix_socket is not None: - return [(socket.AF_UNIX, socket.SOCK_STREAM, None, None, self._unix_socket)] + return [(socket.AF_UNIX, socket.SOCK_STREAM, None, None, + self._unix_socket)] else: - return socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE | socket.AI_ADDRCONFIG) + return socket.getaddrinfo(self.host, + self.port, + socket.AF_UNSPEC, + socket.SOCK_STREAM, + 0, + socket.AI_PASSIVE | socket.AI_ADDRCONFIG) def close(self): if self.handle: self.handle.close() self.handle = None + class TSocket(TSocketBase): """Socket implementation of TTransport base.""" @@ -46,7 +55,6 @@ class TSocket(TSocketBase): @param unix_socket(str) The filename of a unix socket to connect to. (host and port will be ignored.) """ - self.host = host self.port = port self.handle = None @@ -63,7 +71,7 @@ class TSocket(TSocketBase): if ms is None: self._timeout = None else: - self._timeout = ms/1000.0 + self._timeout = ms / 1000.0 if self.handle is not None: self.handle.settimeout(self._timeout) @@ -87,7 +95,8 @@ class TSocket(TSocketBase): message = 'Could not connect to socket %s' % self._unix_socket else: message = 'Could not connect to %s:%d' % (self.host, self.port) - raise TTransportException(type=TTransportException.NOT_OPEN, message=message) + raise TTransportException(type=TTransportException.NOT_OPEN, + message=message) def read(self, sz): try: @@ -105,24 +114,28 @@ class TSocket(TSocketBase): else: raise if len(buff) == 0: - raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket read 0 bytes') + raise TTransportException(type=TTransportException.END_OF_FILE, + message='TSocket read 0 bytes') return buff def write(self, buff): if not self.handle: - raise TTransportException(type=TTransportException.NOT_OPEN, message='Transport not open') + raise TTransportException(type=TTransportException.NOT_OPEN, + message='Transport not open') sent = 0 have = len(buff) while sent < have: plus = self.handle.send(buff) if plus == 0: - raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket sent 0 bytes') + raise TTransportException(type=TTransportException.END_OF_FILE, + message='TSocket sent 0 bytes') sent += plus buff = buff[plus:] def flush(self): pass + class TServerSocket(TSocketBase, TServerTransportBase): """Socket implementation of TServerTransport base.""" diff --git a/module/lib/thrift/transport/TTransport.py b/module/lib/thrift/transport/TTransport.py index 12e51a9bf..4481371a6 100644 --- a/module/lib/thrift/transport/TTransport.py +++ b/module/lib/thrift/transport/TTransport.py @@ -18,11 +18,11 @@ # from cStringIO import StringIO -from struct import pack,unpack +from struct import pack, unpack from thrift.Thrift import TException -class TTransportException(TException): +class TTransportException(TException): """Custom Transport Exception class""" UNKNOWN = 0 @@ -35,8 +35,8 @@ class TTransportException(TException): TException.__init__(self, message) self.type = type -class TTransportBase: +class TTransportBase: """Base class for Thrift transport layer.""" def isOpen(self): @@ -55,7 +55,7 @@ class TTransportBase: buff = '' have = 0 while (have < sz): - chunk = self.read(sz-have) + chunk = self.read(sz - have) have += len(chunk) buff += chunk @@ -70,6 +70,7 @@ class TTransportBase: def flush(self): pass + # This class should be thought of as an interface. class CReadableTransport: """base class for transports that are readable from C""" @@ -98,8 +99,8 @@ class CReadableTransport: """ pass -class TServerTransportBase: +class TServerTransportBase: """Base class for Thrift server transports.""" def listen(self): @@ -111,15 +112,15 @@ class TServerTransportBase: def close(self): pass -class TTransportFactoryBase: +class TTransportFactoryBase: """Base class for a Transport Factory""" def getTransport(self, trans): return trans -class TBufferedTransportFactory: +class TBufferedTransportFactory: """Factory transport that builds buffered transports""" def getTransport(self, trans): @@ -127,17 +128,15 @@ class TBufferedTransportFactory: return buffered -class TBufferedTransport(TTransportBase,CReadableTransport): - +class TBufferedTransport(TTransportBase, CReadableTransport): """Class that wraps another transport and buffers its I/O. The implementation uses a (configurable) fixed-size read buffer but buffers all writes until a flush is performed. """ - DEFAULT_BUFFER = 4096 - def __init__(self, trans, rbuf_size = DEFAULT_BUFFER): + def __init__(self, trans, rbuf_size=DEFAULT_BUFFER): self.__trans = trans self.__wbuf = StringIO() self.__rbuf = StringIO("") @@ -188,6 +187,7 @@ class TBufferedTransport(TTransportBase,CReadableTransport): self.__rbuf = StringIO(retstring) return self.__rbuf + class TMemoryBuffer(TTransportBase, CReadableTransport): """Wraps a cStringIO object as a TTransport. @@ -237,8 +237,8 @@ class TMemoryBuffer(TTransportBase, CReadableTransport): # only one shot at reading... raise EOFError() -class TFramedTransportFactory: +class TFramedTransportFactory: """Factory transport that builds framed transports""" def getTransport(self, trans): @@ -247,7 +247,6 @@ class TFramedTransportFactory: class TFramedTransport(TTransportBase, CReadableTransport): - """Class that wraps another transport and frames its I/O when writing.""" def __init__(self, trans,): diff --git a/module/lib/thrift/transport/TTwisted.py b/module/lib/thrift/transport/TTwisted.py index b6dcb4e0b..3ce3eb220 100644 --- a/module/lib/thrift/transport/TTwisted.py +++ b/module/lib/thrift/transport/TTwisted.py @@ -16,6 +16,9 @@ # specific language governing permissions and limitations # under the License. # + +from cStringIO import StringIO + from zope.interface import implements, Interface, Attribute from twisted.internet.protocol import Protocol, ServerFactory, ClientFactory, \ connectionDone @@ -25,7 +28,6 @@ from twisted.python import log from twisted.web import server, resource, http from thrift.transport import TTransport -from cStringIO import StringIO class TMessageSenderTransport(TTransport.TTransportBase): @@ -79,7 +81,7 @@ class ThriftClientProtocol(basic.Int32StringReceiver): self.started.callback(self.client) def connectionLost(self, reason=connectionDone): - for k,v in self.client._reqs.iteritems(): + for k, v in self.client._reqs.iteritems(): tex = TTransport.TTransportException( type=TTransport.TTransportException.END_OF_FILE, message='Connection closed') diff --git a/module/lib/thrift/transport/TZlibTransport.py b/module/lib/thrift/transport/TZlibTransport.py index 784d4e1e0..a2f42a5d2 100644 --- a/module/lib/thrift/transport/TZlibTransport.py +++ b/module/lib/thrift/transport/TZlibTransport.py @@ -16,50 +16,49 @@ # specific language governing permissions and limitations # under the License. # -''' -TZlibTransport provides a compressed transport and transport factory + +"""TZlibTransport provides a compressed transport and transport factory class, using the python standard library zlib module to implement data compression. -''' +""" from __future__ import division import zlib from cStringIO import StringIO from TTransport import TTransportBase, CReadableTransport + class TZlibTransportFactory(object): - ''' - Factory transport that builds zlib compressed transports. - + """Factory transport that builds zlib compressed transports. + This factory caches the last single client/transport that it was passed and returns the same TZlibTransport object that was created. - + This caching means the TServer class will get the _same_ transport object for both input and output transports from this factory. (For non-threaded scenarios only, since the cache only holds one object) - + The purpose of this caching is to allocate only one TZlibTransport where only one is really needed (since it must have separate read/write buffers), and makes the statistics from getCompSavings() and getCompRatio() easier to understand. - ''' - + """ # class scoped cache of last transport given and zlibtransport returned _last_trans = None _last_z = None def getTransport(self, trans, compresslevel=9): - '''Wrap a transport , trans, with the TZlibTransport + """Wrap a transport, trans, with the TZlibTransport compressed transport class, returning a new transport to the caller. - + @param compresslevel: The zlib compression level, ranging from 0 (no compression) to 9 (best compression). Defaults to 9. @type compresslevel: int - + This method returns a TZlibTransport which wraps the passed C{trans} TTransport derived instance. - ''' + """ if trans == self._last_trans: return self._last_z ztrans = TZlibTransport(trans, compresslevel) @@ -69,27 +68,24 @@ class TZlibTransportFactory(object): class TZlibTransport(TTransportBase, CReadableTransport): - ''' - Class that wraps a transport with zlib, compressing writes + """Class that wraps a transport with zlib, compressing writes and decompresses reads, using the python standard library zlib module. - ''' - + """ # Read buffer size for the python fastbinary C extension, # the TBinaryProtocolAccelerated class. DEFAULT_BUFFSIZE = 4096 def __init__(self, trans, compresslevel=9): - ''' - Create a new TZlibTransport, wrapping C{trans}, another + """Create a new TZlibTransport, wrapping C{trans}, another TTransport derived object. - + @param trans: A thrift transport object, i.e. a TSocket() object. @type trans: TTransport @param compresslevel: The zlib compression level, ranging from 0 (no compression) to 9 (best compression). Default is 9. @type compresslevel: int - ''' + """ self.__trans = trans self.compresslevel = compresslevel self.__rbuf = StringIO() @@ -98,49 +94,45 @@ class TZlibTransport(TTransportBase, CReadableTransport): self._init_stats() def _reinit_buffers(self): - ''' - Internal method to initialize/reset the internal StringIO objects + """Internal method to initialize/reset the internal StringIO objects for read and write buffers. - ''' + """ self.__rbuf = StringIO() self.__wbuf = StringIO() def _init_stats(self): - ''' - Internal method to reset the internal statistics counters + """Internal method to reset the internal statistics counters for compression ratios and bandwidth savings. - ''' + """ self.bytes_in = 0 self.bytes_out = 0 self.bytes_in_comp = 0 self.bytes_out_comp = 0 def _init_zlib(self): - ''' - Internal method for setting up the zlib compression and + """Internal method for setting up the zlib compression and decompression objects. - ''' + """ self._zcomp_read = zlib.decompressobj() self._zcomp_write = zlib.compressobj(self.compresslevel) def getCompRatio(self): - ''' - Get the current measured compression ratios (in,out) from + """Get the current measured compression ratios (in,out) from this transport. - - Returns a tuple of: + + Returns a tuple of: (inbound_compression_ratio, outbound_compression_ratio) - + The compression ratios are computed as: compressed / uncompressed E.g., data that compresses by 10x will have a ratio of: 0.10 and data that compresses to half of ts original size will have a ratio of 0.5 - + None is returned if no bytes have yet been processed in a particular direction. - ''' + """ r_percent, w_percent = (None, None) if self.bytes_in > 0: r_percent = self.bytes_in_comp / self.bytes_in @@ -149,23 +141,22 @@ class TZlibTransport(TTransportBase, CReadableTransport): return (r_percent, w_percent) def getCompSavings(self): - ''' - Get the current count of saved bytes due to data + """Get the current count of saved bytes due to data compression. - + Returns a tuple of: (inbound_saved_bytes, outbound_saved_bytes) - + Note: if compression is actually expanding your data (only likely with very tiny thrift objects), then the values returned will be negative. - ''' + """ r_saved = self.bytes_in - self.bytes_in_comp w_saved = self.bytes_out - self.bytes_out_comp return (r_saved, w_saved) def isOpen(self): - '''Return the underlying transport's open status''' + """Return the underlying transport's open status""" return self.__trans.isOpen() def open(self): @@ -174,25 +165,24 @@ class TZlibTransport(TTransportBase, CReadableTransport): return self.__trans.open() def listen(self): - '''Invoke the underlying transport's listen() method''' + """Invoke the underlying transport's listen() method""" self.__trans.listen() def accept(self): - '''Accept connections on the underlying transport''' + """Accept connections on the underlying transport""" return self.__trans.accept() def close(self): - '''Close the underlying transport,''' + """Close the underlying transport,""" self._reinit_buffers() self._init_zlib() return self.__trans.close() def read(self, sz): - ''' - Read up to sz bytes from the decompressed bytes buffer, and + """Read up to sz bytes from the decompressed bytes buffer, and read from the underlying transport if the decompression buffer is empty. - ''' + """ ret = self.__rbuf.read(sz) if len(ret) > 0: return ret @@ -204,10 +194,9 @@ class TZlibTransport(TTransportBase, CReadableTransport): return ret def readComp(self, sz): - ''' - Read compressed data from the underlying transport, then + """Read compressed data from the underlying transport, then decompress it and append it to the internal StringIO read buffer - ''' + """ zbuf = self.__trans.read(sz) zbuf = self._zcomp_read.unconsumed_tail + zbuf buf = self._zcomp_read.decompress(zbuf) @@ -220,17 +209,15 @@ class TZlibTransport(TTransportBase, CReadableTransport): return True def write(self, buf): - ''' - Write some bytes, putting them into the internal write + """Write some bytes, putting them into the internal write buffer for eventual compression. - ''' + """ self.__wbuf.write(buf) def flush(self): - ''' - Flush any queued up data in the write buffer and ensure the + """Flush any queued up data in the write buffer and ensure the compression buffer is flushed out to the underlying transport - ''' + """ wout = self.__wbuf.getvalue() if len(wout) > 0: zbuf = self._zcomp_write.compress(wout) @@ -247,11 +234,11 @@ class TZlibTransport(TTransportBase, CReadableTransport): @property def cstringio_buf(self): - '''Implement the CReadableTransport interface''' + """Implement the CReadableTransport interface""" return self.__rbuf def cstringio_refill(self, partialread, reqlen): - '''Implement the CReadableTransport interface for refill''' + """Implement the CReadableTransport interface for refill""" retstring = partialread if reqlen < self.DEFAULT_BUFFSIZE: retstring += self.read(self.DEFAULT_BUFFSIZE) diff --git a/module/lib/thrift/transport/__init__.py b/module/lib/thrift/transport/__init__.py index 46e54fe6b..c9596d9a6 100644 --- a/module/lib/thrift/transport/__init__.py +++ b/module/lib/thrift/transport/__init__.py @@ -17,4 +17,4 @@ # under the License. # -__all__ = ['TTransport', 'TSocket', 'THttpClient','TZlibTransport'] +__all__ = ['TTransport', 'TSocket', 'THttpClient', 'TZlibTransport'] diff --git a/module/lib/wsgiserver/__init__.py b/module/lib/wsgiserver/__init__.py index c380e18b0..1058b19ff 100644 --- a/module/lib/wsgiserver/__init__.py +++ b/module/lib/wsgiserver/__init__.py @@ -1,7 +1,7 @@ -"""A high-speed, production ready, thread pooled, generic WSGI server. +"""A high-speed, production ready, thread pooled, generic HTTP server. Simplest example on how to use this module directly -(without using CherryPy's application machinery): +(without using CherryPy's application machinery):: from cherrypy import wsgiserver @@ -9,37 +9,29 @@ Simplest example on how to use this module directly status = '200 OK' response_headers = [('Content-type','text/plain')] start_response(status, response_headers) - return ['Hello world!\n'] + return ['Hello world!'] server = wsgiserver.CherryPyWSGIServer( ('0.0.0.0', 8070), my_crazy_app, server_name='www.cherrypy.example') + server.start() The CherryPy WSGI server can serve as many WSGI applications -as you want in one instance by using a WSGIPathInfoDispatcher: +as you want in one instance by using a WSGIPathInfoDispatcher:: d = WSGIPathInfoDispatcher({'/': my_crazy_app, '/blog': my_blog_app}) server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 80), d) -Want SSL support? Just set these attributes: - - server.ssl_certificate = <filename> - server.ssl_private_key = <filename> - - if __name__ == '__main__': - try: - server.start() - except KeyboardInterrupt: - server.stop() +Want SSL support? Just set server.ssl_adapter to an SSLAdapter instance. This won't call the CherryPy engine (application side) at all, only the -WSGI server, which is independant from the rest of CherryPy. Don't +HTTP server, which is independent from the rest of CherryPy. Don't let the name "CherryPyWSGIServer" throw you; the name merely reflects its origin, not its coupling. For those of you wanting to understand internals of this module, here's the basic call flow. The server's listening thread runs a very tight loop, -sticking incoming connections onto a Queue: +sticking incoming connections onto a Queue:: server = CherryPyWSGIServer(...) server.start() @@ -52,7 +44,7 @@ sticking incoming connections onto a Queue: Worker threads are kept in a pool and poll the Queue, popping off and then handling each connection in turn. Each connection can consist of an arbitrary -number of requests and their responses, so we run a nested loop: +number of requests and their responses, so we run a nested loop:: while True: conn = server.requests.get() @@ -62,9 +54,9 @@ number of requests and their responses, so we run a nested loop: req.parse_request() -> # Read the Request-Line, e.g. "GET /page HTTP/1.1" req.rfile.readline() - req.read_headers() + read_headers(req.rfile, req.inheaders) req.respond() - -> response = wsgi_app(...) + -> response = app(...) try: for chunk in response: if chunk: @@ -76,34 +68,81 @@ number of requests and their responses, so we run a nested loop: return """ +__all__ = ['HTTPRequest', 'HTTPConnection', 'HTTPServer', + 'SizeCheckWrapper', 'KnownLengthRFile', 'ChunkedRFile', + 'CP_fileobject', + 'MaxSizeExceeded', 'NoSSLError', 'FatalSSLAlert', + 'WorkerThread', 'ThreadPool', 'SSLAdapter', + 'CherryPyWSGIServer', + 'Gateway', 'WSGIGateway', 'WSGIGateway_10', 'WSGIGateway_u0', + 'WSGIPathInfoDispatcher'] -import base64 import os -import Queue +try: + import queue +except: + import Queue as queue import re -quoted_slash = re.compile("(?i)%2F") import rfc822 import socket +import sys +if 'win' in sys.platform and not hasattr(socket, 'IPPROTO_IPV6'): + socket.IPPROTO_IPV6 = 41 try: import cStringIO as StringIO except ImportError: import StringIO +DEFAULT_BUFFER_SIZE = -1 _fileobject_uses_str_type = isinstance(socket._fileobject(None)._rbuf, basestring) -import sys import threading import time import traceback +def format_exc(limit=None): + """Like print_exc() but return a string. Backport for Python 2.3.""" + try: + etype, value, tb = sys.exc_info() + return ''.join(traceback.format_exception(etype, value, tb, limit)) + finally: + etype = value = tb = None + + from urllib import unquote from urlparse import urlparse import warnings -try: - from OpenSSL import SSL - from OpenSSL import crypto -except ImportError: - SSL = None +if sys.version_info >= (3, 0): + bytestr = bytes + unicodestr = str + basestring = (bytes, str) + def ntob(n, encoding='ISO-8859-1'): + """Return the given native string as a byte string in the given encoding.""" + # In Python 3, the native string type is unicode + return n.encode(encoding) +else: + bytestr = str + unicodestr = unicode + basestring = basestring + def ntob(n, encoding='ISO-8859-1'): + """Return the given native string as a byte string in the given encoding.""" + # In Python 2, the native string type is bytes. Assume it's already + # in the given encoding, which for ISO-8859-1 is almost always what + # was intended. + return n + +LF = ntob('\n') +CRLF = ntob('\r\n') +TAB = ntob('\t') +SPACE = ntob(' ') +COLON = ntob(':') +SEMICOLON = ntob(';') +EMPTY = ntob('') +NUMBER_SIGN = ntob('#') +QUESTION_MARK = ntob('?') +ASTERISK = ntob('*') +FORWARD_SLASH = ntob('/') +quoted_slash = re.compile(ntob("(?i)%2F")) import errno @@ -117,7 +156,7 @@ def plat_specific_errors(*errnames): errno_names = dir(errno) nums = [getattr(errno, k) for k in errnames if k in errno_names] # de-dupe the list - return dict.fromkeys(nums).keys() + return list(dict.fromkeys(nums).keys()) socket_error_eintr = plat_specific_errors("EINTR", "WSAEINTR") @@ -133,51 +172,71 @@ socket_errors_to_ignore = plat_specific_errors( "EHOSTDOWN", "EHOSTUNREACH", ) socket_errors_to_ignore.append("timed out") +socket_errors_to_ignore.append("The read operation timed out") socket_errors_nonblocking = plat_specific_errors( 'EAGAIN', 'EWOULDBLOCK', 'WSAEWOULDBLOCK') -comma_separated_headers = ['ACCEPT', 'ACCEPT-CHARSET', 'ACCEPT-ENCODING', - 'ACCEPT-LANGUAGE', 'ACCEPT-RANGES', 'ALLOW', 'CACHE-CONTROL', - 'CONNECTION', 'CONTENT-ENCODING', 'CONTENT-LANGUAGE', 'EXPECT', - 'IF-MATCH', 'IF-NONE-MATCH', 'PRAGMA', 'PROXY-AUTHENTICATE', 'TE', - 'TRAILER', 'TRANSFER-ENCODING', 'UPGRADE', 'VARY', 'VIA', 'WARNING', - 'WWW-AUTHENTICATE'] +comma_separated_headers = [ntob(h) for h in + ['Accept', 'Accept-Charset', 'Accept-Encoding', + 'Accept-Language', 'Accept-Ranges', 'Allow', 'Cache-Control', + 'Connection', 'Content-Encoding', 'Content-Language', 'Expect', + 'If-Match', 'If-None-Match', 'Pragma', 'Proxy-Authenticate', 'TE', + 'Trailer', 'Transfer-Encoding', 'Upgrade', 'Vary', 'Via', 'Warning', + 'WWW-Authenticate']] -class WSGIPathInfoDispatcher(object): - """A WSGI dispatcher for dispatch based on the PATH_INFO. +import logging +if not hasattr(logging, 'statistics'): logging.statistics = {} + + +def read_headers(rfile, hdict=None): + """Read headers from the given stream into the given header dict. - apps: a dict or list of (path_prefix, app) pairs. + If hdict is None, a new header dict is created. Returns the populated + header dict. + + Headers which are repeated are folded together using a comma if their + specification so dictates. + + This function raises ValueError when the read bytes violate the HTTP spec. + You should probably return "400 Bad Request" if this happens. """ + if hdict is None: + hdict = {} - def __init__(self, apps): - try: - apps = apps.items() - except AttributeError: - pass + while True: + line = rfile.readline() + if not line: + # No more data--illegal end of headers + raise ValueError("Illegal end of headers.") - # Sort the apps by len(path), descending - apps.sort() - apps.reverse() + if line == CRLF: + # Normal end of headers + break + if not line.endswith(CRLF): + raise ValueError("HTTP requires CRLF terminators") - # The path_prefix strings must start, but not end, with a slash. - # Use "" instead of "/". - self.apps = [(p.rstrip("/"), a) for p, a in apps] - - def __call__(self, environ, start_response): - path = environ["PATH_INFO"] or "/" - for p, app in self.apps: - # The apps list should be sorted by length, descending. - if path.startswith(p + "/") or path == p: - environ = environ.copy() - environ["SCRIPT_NAME"] = environ["SCRIPT_NAME"] + p - environ["PATH_INFO"] = path[len(p):] - return app(environ, start_response) + if line[0] in (SPACE, TAB): + # It's a continuation line. + v = line.strip() + else: + try: + k, v = line.split(COLON, 1) + except ValueError: + raise ValueError("Illegal header line.") + # TODO: what about TE and WWW-Authenticate? + k = k.strip().title() + v = v.strip() + hname = k - start_response('404 Not Found', [('Content-Type', 'text/plain'), - ('Content-Length', '0')]) - return [''] + if k in comma_separated_headers: + existing = hdict.get(hname) + if existing: + v = ", ".join((existing, v)) + hdict[hname] = v + + return hdict class MaxSizeExceeded(Exception): @@ -218,7 +277,7 @@ class SizeCheckWrapper(object): res.append(data) # See http://www.cherrypy.org/ticket/421 if len(data) < 256 or data[-1:] == "\n": - return ''.join(res) + return EMPTY.join(res) def readlines(self, sizehint=0): # Shamelessly stolen from StringIO @@ -239,6 +298,12 @@ class SizeCheckWrapper(object): def __iter__(self): return self + def __next__(self): + data = next(self.rfile) + self.bytes_read += len(data) + self._check_length() + return data + def next(self): data = self.rfile.next() self.bytes_read += len(data) @@ -246,70 +311,293 @@ class SizeCheckWrapper(object): return data +class KnownLengthRFile(object): + """Wraps a file-like object, returning an empty string when exhausted.""" + + def __init__(self, rfile, content_length): + self.rfile = rfile + self.remaining = content_length + + def read(self, size=None): + if self.remaining == 0: + return '' + if size is None: + size = self.remaining + else: + size = min(size, self.remaining) + + data = self.rfile.read(size) + self.remaining -= len(data) + return data + + def readline(self, size=None): + if self.remaining == 0: + return '' + if size is None: + size = self.remaining + else: + size = min(size, self.remaining) + + data = self.rfile.readline(size) + self.remaining -= len(data) + return data + + def readlines(self, sizehint=0): + # Shamelessly stolen from StringIO + total = 0 + lines = [] + line = self.readline(sizehint) + while line: + lines.append(line) + total += len(line) + if 0 < sizehint <= total: + break + line = self.readline(sizehint) + return lines + + def close(self): + self.rfile.close() + + def __iter__(self): + return self + + def __next__(self): + data = next(self.rfile) + self.remaining -= len(data) + return data + + +class ChunkedRFile(object): + """Wraps a file-like object, returning an empty string when exhausted. + + This class is intended to provide a conforming wsgi.input value for + request entities that have been encoded with the 'chunked' transfer + encoding. + """ + + def __init__(self, rfile, maxlen, bufsize=8192): + self.rfile = rfile + self.maxlen = maxlen + self.bytes_read = 0 + self.buffer = EMPTY + self.bufsize = bufsize + self.closed = False + + def _fetch(self): + if self.closed: + return + + line = self.rfile.readline() + self.bytes_read += len(line) + + if self.maxlen and self.bytes_read > self.maxlen: + raise MaxSizeExceeded("Request Entity Too Large", self.maxlen) + + line = line.strip().split(SEMICOLON, 1) + + try: + chunk_size = line.pop(0) + chunk_size = int(chunk_size, 16) + except ValueError: + raise ValueError("Bad chunked transfer size: " + repr(chunk_size)) + + if chunk_size <= 0: + self.closed = True + return + +## if line: chunk_extension = line[0] + + if self.maxlen and self.bytes_read + chunk_size > self.maxlen: + raise IOError("Request Entity Too Large") + + chunk = self.rfile.read(chunk_size) + self.bytes_read += len(chunk) + self.buffer += chunk + + crlf = self.rfile.read(2) + if crlf != CRLF: + raise ValueError( + "Bad chunked transfer coding (expected '\\r\\n', " + "got " + repr(crlf) + ")") + + def read(self, size=None): + data = EMPTY + while True: + if size and len(data) >= size: + return data + + if not self.buffer: + self._fetch() + if not self.buffer: + # EOF + return data + + if size: + remaining = size - len(data) + data += self.buffer[:remaining] + self.buffer = self.buffer[remaining:] + else: + data += self.buffer + + def readline(self, size=None): + data = EMPTY + while True: + if size and len(data) >= size: + return data + + if not self.buffer: + self._fetch() + if not self.buffer: + # EOF + return data + + newline_pos = self.buffer.find(LF) + if size: + if newline_pos == -1: + remaining = size - len(data) + data += self.buffer[:remaining] + self.buffer = self.buffer[remaining:] + else: + remaining = min(size - len(data), newline_pos) + data += self.buffer[:remaining] + self.buffer = self.buffer[remaining:] + else: + if newline_pos == -1: + data += self.buffer + else: + data += self.buffer[:newline_pos] + self.buffer = self.buffer[newline_pos:] + + def readlines(self, sizehint=0): + # Shamelessly stolen from StringIO + total = 0 + lines = [] + line = self.readline(sizehint) + while line: + lines.append(line) + total += len(line) + if 0 < sizehint <= total: + break + line = self.readline(sizehint) + return lines + + def read_trailer_lines(self): + if not self.closed: + raise ValueError( + "Cannot read trailers until the request body has been read.") + + while True: + line = self.rfile.readline() + if not line: + # No more data--illegal end of headers + raise ValueError("Illegal end of headers.") + + self.bytes_read += len(line) + if self.maxlen and self.bytes_read > self.maxlen: + raise IOError("Request Entity Too Large") + + if line == CRLF: + # Normal end of headers + break + if not line.endswith(CRLF): + raise ValueError("HTTP requires CRLF terminators") + + yield line + + def close(self): + self.rfile.close() + + def __iter__(self): + # Shamelessly stolen from StringIO + total = 0 + line = self.readline(sizehint) + while line: + yield line + total += len(line) + if 0 < sizehint <= total: + break + line = self.readline(sizehint) + + class HTTPRequest(object): """An HTTP Request (and response). A single HTTP connection may consist of multiple request/response pairs. - - send: the 'send' method from the connection's socket object. - wsgi_app: the WSGI application to call. - environ: a partial WSGI environ (server and connection entries). - The caller MUST set the following entries: - * All wsgi.* entries, including .input - * SERVER_NAME and SERVER_PORT - * Any SSL_* entries - * Any custom entries like REMOTE_ADDR and REMOTE_PORT - * SERVER_SOFTWARE: the value to write in the "Server" response header. - * ACTUAL_SERVER_PROTOCOL: the value to write in the Status-Line of - the response. From RFC 2145: "An HTTP server SHOULD send a - response version equal to the highest version for which the - server is at least conditionally compliant, and whose major - version is less than or equal to the one received in the - request. An HTTP server MUST NOT send a version for which - it is not at least conditionally compliant." - - outheaders: a list of header tuples to write in the response. - ready: when True, the request has been parsed and is ready to begin - generating the response. When False, signals the calling Connection - that the response should not be generated and the connection should - close. - close_connection: signals the calling Connection that the request - should close. This does not imply an error! The client and/or - server may each request that the connection be closed. - chunked_write: if True, output will be encoded with the "chunked" - transfer-coding. This value is set automatically inside - send_headers. """ - max_request_header_size = 0 - max_request_body_size = 0 + server = None + """The HTTPServer object which is receiving this request.""" - def __init__(self, wfile, environ, wsgi_app): - self.rfile = environ['wsgi.input'] - self.wfile = wfile - self.environ = environ.copy() - self.wsgi_app = wsgi_app + conn = None + """The HTTPConnection object on which this request connected.""" + + inheaders = {} + """A dict of request headers.""" + + outheaders = [] + """A list of header tuples to write in the response.""" + + ready = False + """When True, the request has been parsed and is ready to begin generating + the response. When False, signals the calling Connection that the response + should not be generated and the connection should close.""" + + close_connection = False + """Signals the calling Connection that the request should close. This does + not imply an error! The client and/or server may each request that the + connection be closed.""" + + chunked_write = False + """If True, output will be encoded with the "chunked" transfer-coding. + + This value is set automatically inside send_headers.""" + + def __init__(self, server, conn): + self.server= server + self.conn = conn self.ready = False - self.started_response = False + self.started_request = False + self.scheme = ntob("http") + if self.server.ssl_adapter is not None: + self.scheme = ntob("https") + # Use the lowest-common protocol in case read_request_line errors. + self.response_protocol = 'HTTP/1.0' + self.inheaders = {} + self.status = "" self.outheaders = [] self.sent_headers = False - self.close_connection = False - self.chunked_write = False + self.close_connection = self.__class__.close_connection + self.chunked_read = False + self.chunked_write = self.__class__.chunked_write def parse_request(self): """Parse the next HTTP request start-line and message-headers.""" - self.rfile.maxlen = self.max_request_header_size - self.rfile.bytes_read = 0 + self.rfile = SizeCheckWrapper(self.conn.rfile, + self.server.max_request_header_size) + try: + self.read_request_line() + except MaxSizeExceeded: + self.simple_response("414 Request-URI Too Long", + "The Request-URI sent with the request exceeds the maximum " + "allowed bytes.") + return try: - self._parse_request() + success = self.read_request_headers() except MaxSizeExceeded: - self.simple_response("413 Request Entity Too Large") + self.simple_response("413 Request Entity Too Large", + "The headers sent with the request exceed the maximum " + "allowed bytes.") return + else: + if not success: + return + + self.ready = True - def _parse_request(self): + def read_request_line(self): # HTTP/1.1 connections are persistent by default. If a client # requests a page, then idles (leaves the connection open), # then rfile.readline() will raise socket.error("timed out"). @@ -318,12 +606,16 @@ class HTTPRequest(object): # (although your TCP stack might suffer for it: cf Apache's history # with FIN_WAIT_2). request_line = self.rfile.readline() + + # Set started_request to True so communicate() knows to send 408 + # from here on out. + self.started_request = True if not request_line: # Force self.ready = False so the connection will close. self.ready = False return - if request_line == "\r\n": + if request_line == CRLF: # RFC 2616 sec 4.1: "...if the server is reading the protocol # stream at the beginning of a message and receives a CRLF # first, it should ignore the CRLF." @@ -333,44 +625,53 @@ class HTTPRequest(object): self.ready = False return - environ = self.environ + if not request_line.endswith(CRLF): + self.simple_response("400 Bad Request", "HTTP requires CRLF terminators") + return try: - method, path, req_protocol = request_line.strip().split(" ", 2) - except ValueError: - self.simple_response(400, "Malformed Request-Line") + method, uri, req_protocol = request_line.strip().split(SPACE, 2) + rp = int(req_protocol[5]), int(req_protocol[7]) + except (ValueError, IndexError): + self.simple_response("400 Bad Request", "Malformed Request-Line") return - environ["REQUEST_METHOD"] = method - - # path may be an abs_path (including "http://host.domain.tld"); - scheme, location, path, params, qs, frag = urlparse(path) + self.uri = uri + self.method = method - if frag: + # uri may be an abs_path (including "http://host.domain.tld"); + scheme, authority, path = self.parse_request_uri(uri) + if NUMBER_SIGN in path: self.simple_response("400 Bad Request", "Illegal #fragment in Request-URI.") return if scheme: - environ["wsgi.url_scheme"] = scheme - if params: - path = path + ";" + params + self.scheme = scheme - environ["SCRIPT_NAME"] = "" + qs = EMPTY + if QUESTION_MARK in path: + path, qs = path.split(QUESTION_MARK, 1) - # Unquote the path+params (e.g. "/this%20path" -> "this path"). + # Unquote the path+params (e.g. "/this%20path" -> "/this path"). # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 # # But note that "...a URI must be separated into its components # before the escaped characters within those components can be # safely decoded." http://www.ietf.org/rfc/rfc2396.txt, sec 2.4.2 - atoms = [unquote(x) for x in quoted_slash.split(path)] + # Therefore, "/this%2Fpath" becomes "/this%2Fpath", not "/this/path". + try: + atoms = [unquote(x) for x in quoted_slash.split(path)] + except ValueError: + ex = sys.exc_info()[1] + self.simple_response("400 Bad Request", ex.args[0]) + return path = "%2F".join(atoms) - environ["PATH_INFO"] = path + self.path = path - # Note that, like wsgiref and most other WSGI servers, - # we unquote the path but not the query string. - environ["QUERY_STRING"] = qs + # Note that, like wsgiref and most other HTTP servers, + # we "% HEX HEX"-unquote the path but not the query string. + self.qs = qs # Compare request and server HTTP protocol versions, in case our # server does not support the requested protocol. Limit our output @@ -384,46 +685,46 @@ class HTTPRequest(object): # Notice that, in (b), the response will be "HTTP/1.1" even though # the client only understands 1.0. RFC 2616 10.5.6 says we should # only return 505 if the _major_ version is different. - rp = int(req_protocol[5]), int(req_protocol[7]) - server_protocol = environ["ACTUAL_SERVER_PROTOCOL"] - sp = int(server_protocol[5]), int(server_protocol[7]) + sp = int(self.server.protocol[5]), int(self.server.protocol[7]) + if sp[0] != rp[0]: self.simple_response("505 HTTP Version Not Supported") return - # Bah. "SERVER_PROTOCOL" is actually the REQUEST protocol. - environ["SERVER_PROTOCOL"] = req_protocol + self.request_protocol = req_protocol self.response_protocol = "HTTP/%s.%s" % min(rp, sp) - - # If the Request-URI was an absoluteURI, use its location atom. - if location: - environ["SERVER_NAME"] = location + + def read_request_headers(self): + """Read self.rfile into self.inheaders. Return success.""" # then all the http headers try: - self.read_headers() - except ValueError, ex: - self.simple_response("400 Bad Request", repr(ex.args)) - return + read_headers(self.rfile, self.inheaders) + except ValueError: + ex = sys.exc_info()[1] + self.simple_response("400 Bad Request", ex.args[0]) + return False - mrbs = self.max_request_body_size - if mrbs and int(environ.get("CONTENT_LENGTH", 0)) > mrbs: - self.simple_response("413 Request Entity Too Large") - return + mrbs = self.server.max_request_body_size + if mrbs and int(self.inheaders.get("Content-Length", 0)) > mrbs: + self.simple_response("413 Request Entity Too Large", + "The entity sent with the request exceeds the maximum " + "allowed bytes.") + return False # Persistent connection support if self.response_protocol == "HTTP/1.1": # Both server and client are HTTP/1.1 - if environ.get("HTTP_CONNECTION", "") == "close": + if self.inheaders.get("Connection", "") == "close": self.close_connection = True else: # Either the server or client (or both) are HTTP/1.0 - if environ.get("HTTP_CONNECTION", "") != "Keep-Alive": + if self.inheaders.get("Connection", "") != "Keep-Alive": self.close_connection = True # Transfer-Encoding support te = None if self.response_protocol == "HTTP/1.1": - te = environ.get("HTTP_TRANSFER_ENCODING") + te = self.inheaders.get("Transfer-Encoding") if te: te = [x.strip().lower() for x in te.split(",") if x.strip()] @@ -438,7 +739,7 @@ class HTTPRequest(object): # if there is an extension we don't recognize. self.simple_response("501 Unimplemented") self.close_connection = True - return + return False # From PEP 333: # "Servers and gateways that implement HTTP 1.1 must provide @@ -457,188 +758,128 @@ class HTTPRequest(object): # # We used to do 3, but are now doing 1. Maybe we'll do 2 someday, # but it seems like it would be a big slowdown for such a rare case. - if environ.get("HTTP_EXPECT", "") == "100-continue": - self.simple_response(100) - - self.ready = True + if self.inheaders.get("Expect", "") == "100-continue": + # Don't use simple_response here, because it emits headers + # we don't want. See http://www.cherrypy.org/ticket/951 + msg = self.server.protocol + " 100 Continue\r\n\r\n" + try: + self.conn.wfile.sendall(msg) + except socket.error: + x = sys.exc_info()[1] + if x.args[0] not in socket_errors_to_ignore: + raise + return True - def read_headers(self): - """Read header lines from the incoming stream.""" - environ = self.environ + def parse_request_uri(self, uri): + """Parse a Request-URI into (scheme, authority, path). - while True: - line = self.rfile.readline() - if not line: - # No more data--illegal end of headers - raise ValueError("Illegal end of headers.") - - if line == '\r\n': - # Normal end of headers - break - - if line[0] in ' \t': - # It's a continuation line. - v = line.strip() - else: - k, v = line.split(":", 1) - k, v = k.strip().upper(), v.strip() - envname = "HTTP_" + k.replace("-", "_") + Note that Request-URI's must be one of:: - if k in comma_separated_headers: - existing = environ.get(envname) - if existing: - v = ", ".join((existing, v)) - environ[envname] = v + Request-URI = "*" | absoluteURI | abs_path | authority - ct = environ.pop("HTTP_CONTENT_TYPE", None) - if ct is not None: - environ["CONTENT_TYPE"] = ct - cl = environ.pop("HTTP_CONTENT_LENGTH", None) - if cl is not None: - environ["CONTENT_LENGTH"] = cl - - def decode_chunked(self): - """Decode the 'chunked' transfer coding.""" - cl = 0 - data = StringIO.StringIO() - while True: - line = self.rfile.readline().strip().split(";", 1) - chunk_size = int(line.pop(0), 16) - if chunk_size <= 0: - break -## if line: chunk_extension = line[0] - cl += chunk_size - data.write(self.rfile.read(chunk_size)) - crlf = self.rfile.read(2) - if crlf != "\r\n": - self.simple_response("400 Bad Request", - "Bad chunked transfer coding " - "(expected '\\r\\n', got %r)" % crlf) - return + Therefore, a Request-URI which starts with a double forward-slash + cannot be a "net_path":: - # Grab any trailer headers - self.read_headers() + net_path = "//" authority [ abs_path ] - data.seek(0) - self.environ["wsgi.input"] = data - self.environ["CONTENT_LENGTH"] = str(cl) or "" - return True + Instead, it must be interpreted as an "abs_path" with an empty first + path segment:: + + abs_path = "/" path_segments + path_segments = segment *( "/" segment ) + segment = *pchar *( ";" param ) + param = *pchar + """ + if uri == ASTERISK: + return None, None, uri + + i = uri.find('://') + if i > 0 and QUESTION_MARK not in uri[:i]: + # An absoluteURI. + # If there's a scheme (and it must be http or https), then: + # http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]] + scheme, remainder = uri[:i].lower(), uri[i + 3:] + authority, path = remainder.split(FORWARD_SLASH, 1) + path = FORWARD_SLASH + path + return scheme, authority, path + + if uri.startswith(FORWARD_SLASH): + # An abs_path. + return None, None, uri + else: + # An authority. + return None, uri, None def respond(self): - """Call the appropriate WSGI app and write its iterable output.""" - # Set rfile.maxlen to ensure we don't read past Content-Length. - # This will also be used to read the entire request body if errors - # are raised before the app can read the body. + """Call the gateway and write its iterable output.""" + mrbs = self.server.max_request_body_size if self.chunked_read: - # If chunked, Content-Length will be 0. - self.rfile.maxlen = self.max_request_body_size + self.rfile = ChunkedRFile(self.conn.rfile, mrbs) else: - cl = int(self.environ.get("CONTENT_LENGTH", 0)) - if self.max_request_body_size: - self.rfile.maxlen = min(cl, self.max_request_body_size) - else: - self.rfile.maxlen = cl - self.rfile.bytes_read = 0 - - try: - self._respond() - except MaxSizeExceeded: - if not self.sent_headers: - self.simple_response("413 Request Entity Too Large") - return - - def _respond(self): - if self.chunked_read: - if not self.decode_chunked(): - self.close_connection = True + cl = int(self.inheaders.get("Content-Length", 0)) + if mrbs and mrbs < cl: + if not self.sent_headers: + self.simple_response("413 Request Entity Too Large", + "The entity sent with the request exceeds the maximum " + "allowed bytes.") return + self.rfile = KnownLengthRFile(self.conn.rfile, cl) - response = self.wsgi_app(self.environ, self.start_response) - try: - for chunk in response: - # "The start_response callable must not actually transmit - # the response headers. Instead, it must store them for the - # server or gateway to transmit only after the first - # iteration of the application return value that yields - # a NON-EMPTY string, or upon the application's first - # invocation of the write() callable." (PEP 333) - if chunk: - self.write(chunk) - finally: - if hasattr(response, "close"): - response.close() + self.server.gateway(self).respond() if (self.ready and not self.sent_headers): self.sent_headers = True self.send_headers() if self.chunked_write: - self.wfile.sendall("0\r\n\r\n") + self.conn.wfile.sendall("0\r\n\r\n") def simple_response(self, status, msg=""): """Write a simple response back to the client.""" status = str(status) - buf = ["%s %s\r\n" % (self.environ['ACTUAL_SERVER_PROTOCOL'], status), + buf = [self.server.protocol + SPACE + + status + CRLF, "Content-Length: %s\r\n" % len(msg), "Content-Type: text/plain\r\n"] - if status[:3] == "413" and self.response_protocol == 'HTTP/1.1': - # Request Entity Too Large + if status[:3] in ("413", "414"): + # Request Entity Too Large / Request-URI Too Long self.close_connection = True - buf.append("Connection: close\r\n") + if self.response_protocol == 'HTTP/1.1': + # This will not be true for 414, since read_request_line + # usually raises 414 before reading the whole line, and we + # therefore cannot know the proper response_protocol. + buf.append("Connection: close\r\n") + else: + # HTTP/1.0 had no 413/414 status nor Connection header. + # Emit 400 instead and trust the message body is enough. + status = "400 Bad Request" - buf.append("\r\n") + buf.append(CRLF) if msg: + if isinstance(msg, unicodestr): + msg = msg.encode("ISO-8859-1") buf.append(msg) try: - self.wfile.sendall("".join(buf)) - except socket.error, x: + self.conn.wfile.sendall("".join(buf)) + except socket.error: + x = sys.exc_info()[1] if x.args[0] not in socket_errors_to_ignore: raise - def start_response(self, status, headers, exc_info = None): - """WSGI callable to begin the HTTP response.""" - # "The application may call start_response more than once, - # if and only if the exc_info argument is provided." - if self.started_response and not exc_info: - raise AssertionError("WSGI start_response called a second " - "time with no exc_info.") - - # "if exc_info is provided, and the HTTP headers have already been - # sent, start_response must raise an error, and should raise the - # exc_info tuple." - if self.sent_headers: - try: - raise exc_info[0], exc_info[1], exc_info[2] - finally: - exc_info = None - - self.started_response = True - self.status = status - self.outheaders.extend(headers) - return self.write - def write(self, chunk): - """WSGI callable to write unbuffered data to the client. - - This method is also used internally by start_response (to write - data from the iterable returned by the WSGI application). - """ - if not self.started_response: - raise AssertionError("WSGI write called before start_response.") - - if not self.sent_headers: - self.sent_headers = True - self.send_headers() - + """Write unbuffered data to the client.""" if self.chunked_write and chunk: - buf = [hex(len(chunk))[2:], "\r\n", chunk, "\r\n"] - self.wfile.sendall("".join(buf)) + buf = [hex(len(chunk))[2:], CRLF, chunk, CRLF] + self.conn.wfile.sendall(EMPTY.join(buf)) else: - self.wfile.sendall(chunk) + self.conn.wfile.sendall(chunk) def send_headers(self): - """Assert, process, and send the HTTP response message-headers.""" + """Assert, process, and send the HTTP response message-headers. + + You must set self.status, and self.outheaders before calling this. + """ hkeys = [key.lower() for key, value in self.outheaders] status = int(self.status[:3]) @@ -653,7 +894,7 @@ class HTTPRequest(object): pass else: if (self.response_protocol == 'HTTP/1.1' - and self.environ["REQUEST_METHOD"] != 'HEAD'): + and self.method != 'HEAD'): # Use the chunked transfer-coding self.chunked_write = True self.outheaders.append(("Transfer-Encoding", "chunked")) @@ -684,28 +925,21 @@ class HTTPRequest(object): # requirement is not be construed as preventing a server from # defending itself against denial-of-service attacks, or from # badly broken client implementations." - size = self.rfile.maxlen - self.rfile.bytes_read - if size > 0: - self.rfile.read(size) + remaining = getattr(self.rfile, 'remaining', 0) + if remaining > 0: + self.rfile.read(remaining) if "date" not in hkeys: self.outheaders.append(("Date", rfc822.formatdate())) if "server" not in hkeys: - self.outheaders.append(("Server", self.environ['SERVER_SOFTWARE'])) + self.outheaders.append(("Server", self.server.server_name)) - buf = [self.environ['ACTUAL_SERVER_PROTOCOL'], " ", self.status, "\r\n"] - try: - buf += [k + ": " + v + "\r\n" for k, v in self.outheaders] - except TypeError: - if not isinstance(k, str): - raise TypeError("WSGI response header key %r is not a string.") - if not isinstance(v, str): - raise TypeError("WSGI response header value %r is not a string.") - else: - raise - buf.append("\r\n") - self.wfile.sendall("".join(buf)) + buf = [self.server.protocol + SPACE + self.status + CRLF] + for k, v in self.outheaders: + buf.append(k + COLON + SPACE + v + CRLF) + buf.append(CRLF) + self.conn.wfile.sendall(EMPTY.join(buf)) class NoSSLError(Exception): @@ -718,38 +952,47 @@ class FatalSSLAlert(Exception): pass -if not _fileobject_uses_str_type: - class CP_fileobject(socket._fileobject): - """Faux file object attached to a socket object.""" - - def sendall(self, data): - """Sendall for non-blocking sockets.""" - while data: - try: - bytes_sent = self.send(data) - data = data[bytes_sent:] - except socket.error, e: - if e.args[0] not in socket_errors_nonblocking: - raise - - def send(self, data): - return self._sock.send(data) - - def flush(self): - if self._wbuf: - buffer = "".join(self._wbuf) - self._wbuf = [] - self.sendall(buffer) - - def recv(self, size): - while True: - try: - return self._sock.recv(size) - except socket.error, e: - if (e.args[0] not in socket_errors_nonblocking - and e.args[0] not in socket_error_eintr): - raise +class CP_fileobject(socket._fileobject): + """Faux file object attached to a socket object.""" + def __init__(self, *args, **kwargs): + self.bytes_read = 0 + self.bytes_written = 0 + socket._fileobject.__init__(self, *args, **kwargs) + + def sendall(self, data): + """Sendall for non-blocking sockets.""" + while data: + try: + bytes_sent = self.send(data) + data = data[bytes_sent:] + except socket.error, e: + if e.args[0] not in socket_errors_nonblocking: + raise + + def send(self, data): + bytes_sent = self._sock.send(data) + self.bytes_written += bytes_sent + return bytes_sent + + def flush(self): + if self._wbuf: + buffer = "".join(self._wbuf) + self._wbuf = [] + self.sendall(buffer) + + def recv(self, size): + while True: + try: + data = self._sock.recv(size) + self.bytes_read += len(data) + return data + except socket.error, e: + if (e.args[0] not in socket_errors_nonblocking + and e.args[0] not in socket_error_eintr): + raise + + if not _fileobject_uses_str_type: def read(self, size=-1): # Use max, disallow tiny reads in a loop as they are very inefficient. # We never leave read() with any leftover data from a new recv() call @@ -895,39 +1138,7 @@ if not _fileobject_uses_str_type: buf_len += n #assert buf_len == buf.tell() return buf.getvalue() - -else: - class CP_fileobject(socket._fileobject): - """Faux file object attached to a socket object.""" - - def sendall(self, data): - """Sendall for non-blocking sockets.""" - while data: - try: - bytes_sent = self.send(data) - data = data[bytes_sent:] - except socket.error, e: - if e.args[0] not in socket_errors_nonblocking: - raise - - def send(self, data): - return self._sock.send(data) - - def flush(self): - if self._wbuf: - buffer = "".join(self._wbuf) - self._wbuf = [] - self.sendall(buffer) - - def recv(self, size): - while True: - try: - return self._sock.recv(size) - except socket.error, e: - if (e.args[0] not in socket_errors_nonblocking - and e.args[0] not in socket_error_eintr): - raise - + else: def read(self, size=-1): if size < 0: # Read until EOF @@ -1039,168 +1250,102 @@ else: break buf_len += n return "".join(buffers) - - -class SSL_fileobject(CP_fileobject): - """SSL file object attached to a socket object.""" - - ssl_timeout = 3 - ssl_retry = .01 - - def _safe_call(self, is_reader, call, *args, **kwargs): - """Wrap the given call with SSL error-trapping. - - is_reader: if False EOF errors will be raised. If True, EOF errors - will return "" (to emulate normal sockets). - """ - start = time.time() - while True: - try: - return call(*args, **kwargs) - except SSL.WantReadError: - # Sleep and try again. This is dangerous, because it means - # the rest of the stack has no way of differentiating - # between a "new handshake" error and "client dropped". - # Note this isn't an endless loop: there's a timeout below. - time.sleep(self.ssl_retry) - except SSL.WantWriteError: - time.sleep(self.ssl_retry) - except SSL.SysCallError, e: - if is_reader and e.args == (-1, 'Unexpected EOF'): - return "" - - errnum = e.args[0] - if is_reader and errnum in socket_errors_to_ignore: - return "" - raise socket.error(errnum) - except SSL.Error, e: - if is_reader and e.args == (-1, 'Unexpected EOF'): - return "" - - thirdarg = None - try: - thirdarg = e.args[0][0][2] - except IndexError: - pass - - if thirdarg == 'http request': - # The client is talking HTTP to an HTTPS server. - raise NoSSLError() - raise FatalSSLAlert(*e.args) - except: - raise - - if time.time() - start > self.ssl_timeout: - raise socket.timeout("timed out") - - def recv(self, *args, **kwargs): - buf = [] - r = super(SSL_fileobject, self).recv - while True: - data = self._safe_call(True, r, *args, **kwargs) - buf.append(data) - p = self._sock.pending() - if not p: - return "".join(buf) - - def sendall(self, *args, **kwargs): - return self._safe_call(False, super(SSL_fileobject, self).sendall, *args, **kwargs) - - def send(self, *args, **kwargs): - return self._safe_call(False, super(SSL_fileobject, self).send, *args, **kwargs) class HTTPConnection(object): """An HTTP connection (active socket). + server: the Server object which received this connection. socket: the raw socket object (usually TCP) for this connection. - wsgi_app: the WSGI application for this server/connection. - environ: a WSGI environ template. This will be copied for each request. - - rfile: a fileobject for reading from the socket. - send: a function for writing (+ flush) to the socket. + makefile: a fileobject class for reading from the socket. """ - rbufsize = -1 + remote_addr = None + remote_port = None + ssl_env = None + rbufsize = DEFAULT_BUFFER_SIZE + wbufsize = DEFAULT_BUFFER_SIZE RequestHandlerClass = HTTPRequest - environ = {"wsgi.version": (1, 0), - "wsgi.url_scheme": "http", - "wsgi.multithread": True, - "wsgi.multiprocess": False, - "wsgi.run_once": False, - "wsgi.errors": sys.stderr, - } - - def __init__(self, sock, wsgi_app, environ): + + def __init__(self, server, sock, makefile=CP_fileobject): + self.server = server self.socket = sock - self.wsgi_app = wsgi_app - - # Copy the class environ into self. - self.environ = self.environ.copy() - self.environ.update(environ) - - if SSL and isinstance(sock, SSL.ConnectionType): - timeout = sock.gettimeout() - self.rfile = SSL_fileobject(sock, "rb", self.rbufsize) - self.rfile.ssl_timeout = timeout - self.wfile = SSL_fileobject(sock, "wb", -1) - self.wfile.ssl_timeout = timeout - else: - self.rfile = CP_fileobject(sock, "rb", self.rbufsize) - self.wfile = CP_fileobject(sock, "wb", -1) - - # Wrap wsgi.input but not HTTPConnection.rfile itself. - # We're also not setting maxlen yet; we'll do that separately - # for headers and body for each iteration of self.communicate - # (if maxlen is 0 the wrapper doesn't check length). - self.environ["wsgi.input"] = SizeCheckWrapper(self.rfile, 0) + self.rfile = makefile(sock, "rb", self.rbufsize) + self.wfile = makefile(sock, "wb", self.wbufsize) + self.requests_seen = 0 def communicate(self): """Read each request and respond appropriately.""" + request_seen = False try: while True: # (re)set req to None so that if something goes wrong in # the RequestHandlerClass constructor, the error doesn't # get written to the previous request. req = None - req = self.RequestHandlerClass(self.wfile, self.environ, - self.wsgi_app) + req = self.RequestHandlerClass(self.server, self) # This order of operations should guarantee correct pipelining. req.parse_request() + if self.server.stats['Enabled']: + self.requests_seen += 1 if not req.ready: + # Something went wrong in the parsing (and the server has + # probably already made a simple_response). Return and + # let the conn close. return + request_seen = True req.respond() if req.close_connection: return - - except socket.error, e: + except socket.error: + e = sys.exc_info()[1] errnum = e.args[0] - if errnum == 'timed out': - if req and not req.sent_headers: - req.simple_response("408 Request Timeout") + # sadly SSL sockets return a different (longer) time out string + if errnum == 'timed out' or errnum == 'The read operation timed out': + # Don't error if we're between requests; only error + # if 1) no request has been started at all, or 2) we're + # in the middle of a request. + # See http://www.cherrypy.org/ticket/853 + if (not request_seen) or (req and req.started_request): + # Don't bother writing the 408 if the response + # has already started being written. + if req and not req.sent_headers: + try: + req.simple_response("408 Request Timeout") + except FatalSSLAlert: + # Close the connection. + return elif errnum not in socket_errors_to_ignore: if req and not req.sent_headers: - req.simple_response("500 Internal Server Error", - format_exc()) + try: + req.simple_response("500 Internal Server Error", + format_exc()) + except FatalSSLAlert: + # Close the connection. + return return except (KeyboardInterrupt, SystemExit): raise - except FatalSSLAlert, e: + except FatalSSLAlert: # Close the connection. return except NoSSLError: if req and not req.sent_headers: # Unwrap our wfile - req.wfile = CP_fileobject(self.socket._sock, "wb", -1) + self.wfile = CP_fileobject(self.socket._sock, "wb", self.wbufsize) req.simple_response("400 Bad Request", "The client sent a plain HTTP request, but " "this server only speaks HTTPS on this port.") self.linger = True - except Exception, e: + except Exception: if req and not req.sent_headers: - req.simple_response("500 Internal Server Error", format_exc()) + try: + req.simple_response("500 Internal Server Error", format_exc()) + except FatalSSLAlert: + # Close the connection. + return linger = False @@ -1214,7 +1359,8 @@ class HTTPConnection(object): # want this server to send a FIN TCP segment immediately. Note this # must be called *before* calling socket.close(), because the latter # drops its reference to the kernel socket. - self.socket._sock.close() + if hasattr(self.socket, '_sock'): + self.socket._sock.close() self.socket.close() else: # On the other hand, sometimes we want to hang around for a bit @@ -1226,13 +1372,13 @@ class HTTPConnection(object): pass -def format_exc(limit=None): - """Like print_exc() but return a string. Backport for Python 2.3.""" - try: - etype, value, tb = sys.exc_info() - return ''.join(traceback.format_exception(etype, value, tb, limit)) - finally: - etype = value = tb = None +class TrueyZero(object): + """An object which equals and does math like the integer '0' but evals True.""" + def __add__(self, other): + return other + def __radd__(self, other): + return other +trueyzero = TrueyZero() _SHUTDOWNREQUEST = None @@ -1240,11 +1386,6 @@ _SHUTDOWNREQUEST = None class WorkerThread(threading.Thread): """Thread which continuously polls a Queue for Connection objects. - server: the HTTP Server which spawned this thread, and which owns the - Queue and is placing active connections into it. - ready: a simple flag for the calling server to know when this thread - has begun polling the Queue. - Due to the timing issues of polling a Queue, a WorkerThread does not check its own 'ready' flag after it has started. To stop the thread, it is necessary to stick a _SHUTDOWNREQUEST object onto the Queue @@ -1252,13 +1393,38 @@ class WorkerThread(threading.Thread): """ conn = None + """The current connection pulled off the Queue, or None.""" + + server = None + """The HTTP Server which spawned this thread, and which owns the + Queue and is placing active connections into it.""" + + ready = False + """A simple flag for the calling server to know when this thread + has begun polling the Queue.""" + def __init__(self, server): self.ready = False self.server = server + + self.requests_seen = 0 + self.bytes_read = 0 + self.bytes_written = 0 + self.start_time = None + self.work_time = 0 + self.stats = { + 'Requests': lambda s: self.requests_seen + ((self.start_time is None) and trueyzero or self.conn.requests_seen), + 'Bytes Read': lambda s: self.bytes_read + ((self.start_time is None) and trueyzero or self.conn.rfile.bytes_read), + 'Bytes Written': lambda s: self.bytes_written + ((self.start_time is None) and trueyzero or self.conn.wfile.bytes_written), + 'Work Time': lambda s: self.work_time + ((self.start_time is None) and trueyzero or time.time() - self.start_time), + 'Read Throughput': lambda s: s['Bytes Read'](s) / (s['Work Time'](s) or 1e-6), + 'Write Throughput': lambda s: s['Bytes Written'](s) / (s['Work Time'](s) or 1e-6), + } threading.Thread.__init__(self) def run(self): + self.server.stats['Worker Threads'][self.getName()] = self.stats try: self.ready = True while True: @@ -1267,17 +1433,26 @@ class WorkerThread(threading.Thread): return self.conn = conn + if self.server.stats['Enabled']: + self.start_time = time.time() try: conn.communicate() finally: conn.close() + if self.server.stats['Enabled']: + self.requests_seen += self.conn.requests_seen + self.bytes_read += self.conn.rfile.bytes_read + self.bytes_written += self.conn.wfile.bytes_written + self.work_time += time.time() - self.start_time + self.start_time = None self.conn = None - except (KeyboardInterrupt, SystemExit), exc: + except (KeyboardInterrupt, SystemExit): + exc = sys.exc_info()[1] self.server.interrupt = exc class ThreadPool(object): - """A Request Queue for the CherryPyWSGIServer which pools threads. + """A Request Queue for an HTTPServer which pools threads. ThreadPool objects must provide min, get(), put(obj), start() and stop(timeout) attributes. @@ -1288,15 +1463,15 @@ class ThreadPool(object): self.min = min self.max = max self._threads = [] - self._queue = Queue.Queue() + self._queue = queue.Queue() self.get = self._queue.get def start(self): """Start the pool of threads.""" - for i in xrange(self.min): + for i in range(self.min): self._threads.append(WorkerThread(self.server)) for worker in self._threads: - worker.setName("CP WSGIServer " + worker.getName()) + worker.setName("CP Server " + worker.getName()) worker.start() for worker in self._threads: while not worker.ready: @@ -1314,11 +1489,11 @@ class ThreadPool(object): def grow(self, amount): """Spawn new worker threads (not above self.max).""" - for i in xrange(amount): + for i in range(amount): if self.max > 0 and len(self._threads) >= self.max: break worker = WorkerThread(self.server) - worker.setName("CP WSGIServer " + worker.getName()) + worker.setName("CP Server " + worker.getName()) self._threads.append(worker) worker.start() @@ -1332,7 +1507,7 @@ class ThreadPool(object): amount -= 1 if amount > 0: - for i in xrange(min(amount, len(self._threads) - self.min)): + for i in range(min(amount, len(self._threads) - self.min)): # Put a number of shutdown requests on the queue equal # to 'amount'. Once each of those is processed by a worker, # that worker will terminate and be culled from our list @@ -1347,6 +1522,8 @@ class ThreadPool(object): # Don't join currentThread (when stop is called inside a request). current = threading.currentThread() + if timeout and timeout >= 0: + endtime = time.time() + timeout while self._threads: worker = self._threads.pop() if worker is not current and worker.isAlive(): @@ -1354,51 +1531,30 @@ class ThreadPool(object): if timeout is None or timeout < 0: worker.join() else: - worker.join(timeout) + remaining_time = endtime - time.time() + if remaining_time > 0: + worker.join(remaining_time) if worker.isAlive(): # We exhausted the timeout. # Forcibly shut down the socket. c = worker.conn if c and not c.rfile.closed: - if SSL and isinstance(c.socket, SSL.ConnectionType): - # pyOpenSSL.socket.shutdown takes no args - c.socket.shutdown() - else: + try: c.socket.shutdown(socket.SHUT_RD) + except TypeError: + # pyOpenSSL sockets don't take an arg + c.socket.shutdown() worker.join() except (AssertionError, # Ignore repeated Ctrl-C. # See http://www.cherrypy.org/ticket/691. - KeyboardInterrupt), exc1: + KeyboardInterrupt): pass - - - -class SSLConnection: - """A thread-safe wrapper for an SSL.Connection. - - *args: the arguments to create the wrapped SSL.Connection(*args). - """ - def __init__(self, *args): - self._ssl_conn = SSL.Connection(*args) - self._lock = threading.RLock() - - for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read', - 'renegotiate', 'bind', 'listen', 'connect', 'accept', - 'setblocking', 'fileno', 'shutdown', 'close', 'get_cipher_list', - 'getpeername', 'getsockname', 'getsockopt', 'setsockopt', - 'makefile', 'get_app_data', 'set_app_data', 'state_string', - 'sock_shutdown', 'get_peer_certificate', 'want_read', - 'want_write', 'set_connect_state', 'set_accept_state', - 'connect_ex', 'sendall', 'settimeout'): - exec """def %s(self, *args): - self._lock.acquire() - try: - return self._ssl_conn.%s(*args) - finally: - self._lock.release() -""" % (f, f) + def _get_qsize(self): + return self._queue.qsize() + qsize = property(_get_qsize) + try: @@ -1423,96 +1579,136 @@ else: fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC) -class CherryPyWSGIServer(object): - """An HTTP server for WSGI. +class SSLAdapter(object): + """Base class for SSL driver library adapters. - bind_addr: The interface on which to listen for connections. - For TCP sockets, a (host, port) tuple. Host values may be any IPv4 - or IPv6 address, or any valid hostname. The string 'localhost' is a - synonym for '127.0.0.1' (or '::1', if your hosts file prefers IPv6). - The string '0.0.0.0' is a special IPv4 entry meaning "any active - interface" (INADDR_ANY), and '::' is the similar IN6ADDR_ANY for - IPv6. The empty string or None are not allowed. - - For UNIX sockets, supply the filename as a string. - wsgi_app: the WSGI 'application callable'; multiple WSGI applications - may be passed as (path_prefix, app) pairs. - numthreads: the number of worker threads to create (default 10). - server_name: the string to set for WSGI's SERVER_NAME environ entry. - Defaults to socket.gethostname(). - max: the maximum number of queued requests (defaults to -1 = no limit). - request_queue_size: the 'backlog' argument to socket.listen(); - specifies the maximum number of queued connections (default 5). - timeout: the timeout in seconds for accepted connections (default 10). + Required methods: - nodelay: if True (the default since 3.1), sets the TCP_NODELAY socket - option. + * ``wrap(sock) -> (wrapped socket, ssl environ dict)`` + * ``makefile(sock, mode='r', bufsize=DEFAULT_BUFFER_SIZE) -> socket file object`` + """ - protocol: the version string to write in the Status-Line of all - HTTP responses. For example, "HTTP/1.1" (the default). This - also limits the supported features used in the response. + def __init__(self, certificate, private_key, certificate_chain=None): + self.certificate = certificate + self.private_key = private_key + self.certificate_chain = certificate_chain + def wrap(self, sock): + raise NotImplemented - SSL/HTTPS - --------- - The OpenSSL module must be importable for SSL functionality. - You can obtain it from http://pyopenssl.sourceforge.net/ + def makefile(self, sock, mode='r', bufsize=DEFAULT_BUFFER_SIZE): + raise NotImplemented + + +class HTTPServer(object): + """An HTTP server.""" - ssl_certificate: the filename of the server SSL certificate. - ssl_privatekey: the filename of the server's private key file. + _bind_addr = "127.0.0.1" + _interrupt = None - If either of these is None (both are None by default), this server - will not use SSL. If both are given and are valid, they will be read - on server start and used in the SSL context for the listening socket. - """ + gateway = None + """A Gateway instance.""" + + minthreads = None + """The minimum number of worker threads to create (default 10).""" + + maxthreads = None + """The maximum number of worker threads to create (default -1 = no limit).""" + + server_name = None + """The name of the server; defaults to socket.gethostname().""" protocol = "HTTP/1.1" - _bind_addr = "127.0.0.1" - version = "CherryPy/3.1.2" + """The version string to write in the Status-Line of all HTTP responses. + + For example, "HTTP/1.1" is the default. This also limits the supported + features used in the response.""" + + request_queue_size = 5 + """The 'backlog' arg to socket.listen(); max queued connections (default 5).""" + + shutdown_timeout = 5 + """The total time, in seconds, to wait for worker threads to cleanly exit.""" + + timeout = 10 + """The timeout in seconds for accepted connections (default 10).""" + + version = "CherryPy/3.2.1" + """A version string for the HTTPServer.""" + + software = None + """The value to set for the SERVER_SOFTWARE entry in the WSGI environ. + + If None, this defaults to ``'%s Server' % self.version``.""" + ready = False - _interrupt = None + """An internal flag which marks whether the socket is accepting connections.""" + + max_request_header_size = 0 + """The maximum size, in bytes, for request headers, or 0 for no limit.""" + + max_request_body_size = 0 + """The maximum size, in bytes, for request bodies, or 0 for no limit.""" nodelay = True + """If True (the default since 3.1), sets the TCP_NODELAY socket option.""" ConnectionClass = HTTPConnection - environ = {} + """The class to use for handling HTTP connections.""" - # Paths to certificate and private key files - ssl_certificate = None - ssl_private_key = None + ssl_adapter = None + """An instance of SSLAdapter (or a subclass). - def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None, - max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5): - self.requests = ThreadPool(self, min=numthreads or 1, max=max) + You must have the corresponding SSL driver library installed.""" + + def __init__(self, bind_addr, gateway, minthreads=10, maxthreads=-1, + server_name=None): + self.bind_addr = bind_addr + self.gateway = gateway - if callable(wsgi_app): - # We've been handed a single wsgi_app, in CP-2.1 style. - # Assume it's mounted at "". - self.wsgi_app = wsgi_app - else: - # We've been handed a list of (path_prefix, wsgi_app) tuples, - # so that the server can call different wsgi_apps, and also - # correctly set SCRIPT_NAME. - warnings.warn("The ability to pass multiple apps is deprecated " - "and will be removed in 3.2. You should explicitly " - "include a WSGIPathInfoDispatcher instead.", - DeprecationWarning) - self.wsgi_app = WSGIPathInfoDispatcher(wsgi_app) + self.requests = ThreadPool(self, min=minthreads or 1, max=maxthreads) - self.bind_addr = bind_addr if not server_name: server_name = socket.gethostname() self.server_name = server_name - self.request_queue_size = request_queue_size - - self.timeout = timeout - self.shutdown_timeout = shutdown_timeout + self.clear_stats() + + def clear_stats(self): + self._start_time = None + self._run_time = 0 + self.stats = { + 'Enabled': False, + 'Bind Address': lambda s: repr(self.bind_addr), + 'Run time': lambda s: (not s['Enabled']) and -1 or self.runtime(), + 'Accepts': 0, + 'Accepts/sec': lambda s: s['Accepts'] / self.runtime(), + 'Queue': lambda s: getattr(self.requests, "qsize", None), + 'Threads': lambda s: len(getattr(self.requests, "_threads", [])), + 'Threads Idle': lambda s: getattr(self.requests, "idle", None), + 'Socket Errors': 0, + 'Requests': lambda s: (not s['Enabled']) and -1 or sum([w['Requests'](w) for w + in s['Worker Threads'].values()], 0), + 'Bytes Read': lambda s: (not s['Enabled']) and -1 or sum([w['Bytes Read'](w) for w + in s['Worker Threads'].values()], 0), + 'Bytes Written': lambda s: (not s['Enabled']) and -1 or sum([w['Bytes Written'](w) for w + in s['Worker Threads'].values()], 0), + 'Work Time': lambda s: (not s['Enabled']) and -1 or sum([w['Work Time'](w) for w + in s['Worker Threads'].values()], 0), + 'Read Throughput': lambda s: (not s['Enabled']) and -1 or sum( + [w['Bytes Read'](w) / (w['Work Time'](w) or 1e-6) + for w in s['Worker Threads'].values()], 0), + 'Write Throughput': lambda s: (not s['Enabled']) and -1 or sum( + [w['Bytes Written'](w) / (w['Work Time'](w) or 1e-6) + for w in s['Worker Threads'].values()], 0), + 'Worker Threads': {}, + } + logging.statistics["CherryPy HTTPServer %d" % id(self)] = self.stats - def _get_numthreads(self): - return self.requests.min - def _set_numthreads(self, value): - self.requests.min = value - numthreads = property(_get_numthreads, _set_numthreads) + def runtime(self): + if self._start_time is None: + return self._run_time + else: + return self._run_time + (time.time() - self._start_time) def __str__(self): return "%s.%s(%r)" % (self.__module__, self.__class__.__name__, @@ -1556,6 +1752,28 @@ class CherryPyWSGIServer(object): # trap those exceptions in whatever code block calls start(). self._interrupt = None + if self.software is None: + self.software = "%s Server" % self.version + + # SSL backward compatibility + if (self.ssl_adapter is None and + getattr(self, 'ssl_certificate', None) and + getattr(self, 'ssl_private_key', None)): + warnings.warn( + "SSL attributes are deprecated in CherryPy 3.2, and will " + "be removed in CherryPy 3.3. Use an ssl_adapter attribute " + "instead.", + DeprecationWarning + ) + try: + from cherrypy.wsgiserver.ssl_pyopenssl import pyOpenSSLAdapter + except ImportError: + pass + else: + self.ssl_adapter = pyOpenSSLAdapter( + self.ssl_certificate, self.ssl_private_key, + getattr(self, 'ssl_certificate_chain', None)) + # Select the appropriate socket if isinstance(self.bind_addr, basestring): # AF_UNIX socket @@ -1565,7 +1783,7 @@ class CherryPyWSGIServer(object): except: pass # So everyone can access the socket... - try: os.chmod(self.bind_addr, 0777) + try: os.chmod(self.bind_addr, 511) # 0777 except: pass info = [(socket.AF_UNIX, socket.SOCK_STREAM, 0, "", self.bind_addr)] @@ -1577,8 +1795,12 @@ class CherryPyWSGIServer(object): info = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) except socket.gaierror: - # Probably a DNS issue. Assume IPv4. - info = [(socket.AF_INET, socket.SOCK_STREAM, 0, "", self.bind_addr)] + if ':' in self.bind_addr[0]: + info = [(socket.AF_INET6, socket.SOCK_STREAM, + 0, "", self.bind_addr + (0, 0))] + else: + info = [(socket.AF_INET, socket.SOCK_STREAM, + 0, "", self.bind_addr)] self.socket = None msg = "No socket could be created" @@ -1586,14 +1808,14 @@ class CherryPyWSGIServer(object): af, socktype, proto, canonname, sa = res try: self.bind(af, socktype, proto) - except socket.error, msg: + except socket.error: if self.socket: self.socket.close() self.socket = None continue break if not self.socket: - raise socket.error, msg + raise socket.error(msg) # Timeout so KeyboardInterrupt can be caught on Win32 self.socket.settimeout(1) @@ -1603,6 +1825,7 @@ class CherryPyWSGIServer(object): self.requests.start() self.ready = True + self._start_time = time.time() while self.ready: self.tick() if self.interrupt: @@ -1617,29 +1840,22 @@ class CherryPyWSGIServer(object): self.socket = socket.socket(family, type, proto) prevent_socket_inheritance(self.socket) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - if self.nodelay: + if self.nodelay and not isinstance(self.bind_addr, str): self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - if self.ssl_certificate and self.ssl_private_key: - if SSL is None: - raise ImportError("You must install pyOpenSSL to use HTTPS.") - - # See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473 - ctx = SSL.Context(SSL.SSLv23_METHOD) - ctx.use_privatekey_file(self.ssl_private_key) - ctx.use_certificate_file(self.ssl_certificate) - self.socket = SSLConnection(ctx, self.socket) - self.populate_ssl_environ() - - # If listening on the IPV6 any address ('::' = IN6ADDR_ANY), - # activate dual-stack. See http://www.cherrypy.org/ticket/871. - if (not isinstance(self.bind_addr, basestring) - and self.bind_addr[0] == '::' and family == socket.AF_INET6): - try: - self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) - except (AttributeError, socket.error): - # Apparently, the socket option is not available in - # this machine's TCP stack - pass + + if self.ssl_adapter is not None: + self.socket = self.ssl_adapter.bind(self.socket) + + # If listening on the IPV6 any address ('::' = IN6ADDR_ANY), + # activate dual-stack. See http://www.cherrypy.org/ticket/871. + if (hasattr(socket, 'AF_INET6') and family == socket.AF_INET6 + and self.bind_addr[0] in ('::', '::0', '::0.0.0.0')): + try: + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) + except (AttributeError, socket.error): + # Apparently, the socket option is not available in + # this machine's TCP stack + pass self.socket.bind(self.bind_addr) @@ -1647,42 +1863,72 @@ class CherryPyWSGIServer(object): """Accept a new connection and put it on the Queue.""" try: s, addr = self.socket.accept() - prevent_socket_inheritance(s) + if self.stats['Enabled']: + self.stats['Accepts'] += 1 if not self.ready: return + + prevent_socket_inheritance(s) if hasattr(s, 'settimeout'): s.settimeout(self.timeout) - environ = self.environ.copy() - # SERVER_SOFTWARE is common for IIS. It's also helpful for - # us to pass a default value for the "Server" response header. - if environ.get("SERVER_SOFTWARE") is None: - environ["SERVER_SOFTWARE"] = "%s WSGI Server" % self.version - # set a non-standard environ entry so the WSGI app can know what - # the *real* server protocol is (and what features to support). - # See http://www.faqs.org/rfcs/rfc2145.html. - environ["ACTUAL_SERVER_PROTOCOL"] = self.protocol - environ["SERVER_NAME"] = self.server_name + makefile = CP_fileobject + ssl_env = {} + # if ssl cert and key are set, we try to be a secure HTTP server + if self.ssl_adapter is not None: + try: + s, ssl_env = self.ssl_adapter.wrap(s) + except NoSSLError: + msg = ("The client sent a plain HTTP request, but " + "this server only speaks HTTPS on this port.") + buf = ["%s 400 Bad Request\r\n" % self.protocol, + "Content-Length: %s\r\n" % len(msg), + "Content-Type: text/plain\r\n\r\n", + msg] + + wfile = makefile(s, "wb", DEFAULT_BUFFER_SIZE) + try: + wfile.sendall("".join(buf)) + except socket.error: + x = sys.exc_info()[1] + if x.args[0] not in socket_errors_to_ignore: + raise + return + if not s: + return + makefile = self.ssl_adapter.makefile + # Re-apply our timeout since we may have a new socket object + if hasattr(s, 'settimeout'): + s.settimeout(self.timeout) - if isinstance(self.bind_addr, basestring): - # AF_UNIX. This isn't really allowed by WSGI, which doesn't - # address unix domain sockets. But it's better than nothing. - environ["SERVER_PORT"] = "" - else: - environ["SERVER_PORT"] = str(self.bind_addr[1]) + conn = self.ConnectionClass(self, s, makefile) + + if not isinstance(self.bind_addr, basestring): # optional values # Until we do DNS lookups, omit REMOTE_HOST - environ["REMOTE_ADDR"] = addr[0] - environ["REMOTE_PORT"] = str(addr[1]) + if addr is None: # sometimes this can happen + # figure out if AF_INET or AF_INET6. + if len(s.getsockname()) == 2: + # AF_INET + addr = ('0.0.0.0', 0) + else: + # AF_INET6 + addr = ('::', 0) + conn.remote_addr = addr[0] + conn.remote_port = addr[1] + + conn.ssl_env = ssl_env - conn = self.ConnectionClass(s, self.wsgi_app, environ) self.requests.put(conn) except socket.timeout: # The only reason for the timeout in start() is so we can # notice keyboard interrupts on Win32, which don't interrupt # accept() by default return - except socket.error, x: + except socket.error: + x = sys.exc_info()[1] + if self.stats['Enabled']: + self.stats['Socket Errors'] += 1 if x.args[0] in socket_error_eintr: # I *think* this is right. EINTR should occur when a signal # is received during the accept() call; all docs say retry @@ -1712,6 +1958,9 @@ class CherryPyWSGIServer(object): def stop(self): """Gracefully shutdown a server that is serving forever.""" self.ready = False + if self._start_time is not None: + self._run_time += (time.time() - self._start_time) + self._start_time = None sock = getattr(self, "socket", None) if sock: @@ -1719,8 +1968,11 @@ class CherryPyWSGIServer(object): # Touch our own socket to make accept() return immediately. try: host, port = sock.getsockname()[:2] - except socket.error, x: + except socket.error: + x = sys.exc_info()[1] if x.args[0] not in socket_errors_to_ignore: + # Changed to use error code and not message + # See http://www.cherrypy.org/ticket/860. raise else: # Note that we're explicitly NOT using AI_PASSIVE, @@ -1746,49 +1998,302 @@ class CherryPyWSGIServer(object): self.socket = None self.requests.stop(self.shutdown_timeout) + + +class Gateway(object): + """A base class to interface HTTPServer with other systems, such as WSGI.""" + + def __init__(self, req): + self.req = req + + def respond(self): + """Process the current request. Must be overridden in a subclass.""" + raise NotImplemented + + +# These may either be wsgiserver.SSLAdapter subclasses or the string names +# of such classes (in which case they will be lazily loaded). +ssl_adapters = { + 'builtin': 'cherrypy.wsgiserver.ssl_builtin.BuiltinSSLAdapter', + 'pyopenssl': 'cherrypy.wsgiserver.ssl_pyopenssl.pyOpenSSLAdapter', + } + +def get_ssl_adapter_class(name='pyopenssl'): + """Return an SSL adapter class for the given name.""" + adapter = ssl_adapters[name.lower()] + if isinstance(adapter, basestring): + last_dot = adapter.rfind(".") + attr_name = adapter[last_dot + 1:] + mod_path = adapter[:last_dot] + + try: + mod = sys.modules[mod_path] + if mod is None: + raise KeyError() + except KeyError: + # The last [''] is important. + mod = __import__(mod_path, globals(), locals(), ['']) + + # Let an AttributeError propagate outward. + try: + adapter = getattr(mod, attr_name) + except AttributeError: + raise AttributeError("'%s' object has no attribute '%s'" + % (mod_path, attr_name)) + + return adapter + +# -------------------------------- WSGI Stuff -------------------------------- # + + +class CherryPyWSGIServer(HTTPServer): + """A subclass of HTTPServer which calls a WSGI application.""" + + wsgi_version = (1, 0) + """The version of WSGI to produce.""" + + def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None, + max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5): + self.requests = ThreadPool(self, min=numthreads or 1, max=max) + self.wsgi_app = wsgi_app + self.gateway = wsgi_gateways[self.wsgi_version] + + self.bind_addr = bind_addr + if not server_name: + server_name = socket.gethostname() + self.server_name = server_name + self.request_queue_size = request_queue_size + + self.timeout = timeout + self.shutdown_timeout = shutdown_timeout + self.clear_stats() + + def _get_numthreads(self): + return self.requests.min + def _set_numthreads(self, value): + self.requests.min = value + numthreads = property(_get_numthreads, _set_numthreads) + + +class WSGIGateway(Gateway): + """A base class to interface HTTPServer with WSGI.""" + + def __init__(self, req): + self.req = req + self.started_response = False + self.env = self.get_environ() + self.remaining_bytes_out = None - def populate_ssl_environ(self): - """Create WSGI environ entries to be merged into each request.""" - cert = open(self.ssl_certificate, 'rb').read() - cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert) - ssl_environ = { - "wsgi.url_scheme": "https", - "HTTPS": "on", - # pyOpenSSL doesn't provide access to any of these AFAICT -## 'SSL_PROTOCOL': 'SSLv2', -## SSL_CIPHER string The cipher specification name -## SSL_VERSION_INTERFACE string The mod_ssl program version -## SSL_VERSION_LIBRARY string The OpenSSL program version + def get_environ(self): + """Return a new environ dict targeting the given wsgi.version""" + raise NotImplemented + + def respond(self): + """Process the current request.""" + response = self.req.server.wsgi_app(self.env, self.start_response) + try: + for chunk in response: + # "The start_response callable must not actually transmit + # the response headers. Instead, it must store them for the + # server or gateway to transmit only after the first + # iteration of the application return value that yields + # a NON-EMPTY string, or upon the application's first + # invocation of the write() callable." (PEP 333) + if chunk: + if isinstance(chunk, unicodestr): + chunk = chunk.encode('ISO-8859-1') + self.write(chunk) + finally: + if hasattr(response, "close"): + response.close() + + def start_response(self, status, headers, exc_info = None): + """WSGI callable to begin the HTTP response.""" + # "The application may call start_response more than once, + # if and only if the exc_info argument is provided." + if self.started_response and not exc_info: + raise AssertionError("WSGI start_response called a second " + "time with no exc_info.") + self.started_response = True + + # "if exc_info is provided, and the HTTP headers have already been + # sent, start_response must raise an error, and should raise the + # exc_info tuple." + if self.req.sent_headers: + try: + raise exc_info[0], exc_info[1], exc_info[2] + finally: + exc_info = None + + self.req.status = status + for k, v in headers: + if not isinstance(k, bytestr): + raise TypeError("WSGI response header key %r is not a byte string." % k) + if not isinstance(v, bytestr): + raise TypeError("WSGI response header value %r is not a byte string." % v) + if k.lower() == 'content-length': + self.remaining_bytes_out = int(v) + self.req.outheaders.extend(headers) + + return self.write + + def write(self, chunk): + """WSGI callable to write unbuffered data to the client. + + This method is also used internally by start_response (to write + data from the iterable returned by the WSGI application). + """ + if not self.started_response: + raise AssertionError("WSGI write called before start_response.") + + chunklen = len(chunk) + rbo = self.remaining_bytes_out + if rbo is not None and chunklen > rbo: + if not self.req.sent_headers: + # Whew. We can send a 500 to the client. + self.req.simple_response("500 Internal Server Error", + "The requested resource returned more bytes than the " + "declared Content-Length.") + else: + # Dang. We have probably already sent data. Truncate the chunk + # to fit (so the client doesn't hang) and raise an error later. + chunk = chunk[:rbo] + + if not self.req.sent_headers: + self.req.sent_headers = True + self.req.send_headers() + + self.req.write(chunk) + + if rbo is not None: + rbo -= chunklen + if rbo < 0: + raise ValueError( + "Response body exceeds the declared Content-Length.") + + +class WSGIGateway_10(WSGIGateway): + """A Gateway class to interface HTTPServer with WSGI 1.0.x.""" + + def get_environ(self): + """Return a new environ dict targeting the given wsgi.version""" + req = self.req + env = { + # set a non-standard environ entry so the WSGI app can know what + # the *real* server protocol is (and what features to support). + # See http://www.faqs.org/rfcs/rfc2145.html. + 'ACTUAL_SERVER_PROTOCOL': req.server.protocol, + 'PATH_INFO': req.path, + 'QUERY_STRING': req.qs, + 'REMOTE_ADDR': req.conn.remote_addr or '', + 'REMOTE_PORT': str(req.conn.remote_port or ''), + 'REQUEST_METHOD': req.method, + 'REQUEST_URI': req.uri, + 'SCRIPT_NAME': '', + 'SERVER_NAME': req.server.server_name, + # Bah. "SERVER_PROTOCOL" is actually the REQUEST protocol. + 'SERVER_PROTOCOL': req.request_protocol, + 'SERVER_SOFTWARE': req.server.software, + 'wsgi.errors': sys.stderr, + 'wsgi.input': req.rfile, + 'wsgi.multiprocess': False, + 'wsgi.multithread': True, + 'wsgi.run_once': False, + 'wsgi.url_scheme': req.scheme, + 'wsgi.version': (1, 0), } - # Server certificate attributes - ssl_environ.update({ - 'SSL_SERVER_M_VERSION': cert.get_version(), - 'SSL_SERVER_M_SERIAL': cert.get_serial_number(), -## 'SSL_SERVER_V_START': Validity of server's certificate (start time), -## 'SSL_SERVER_V_END': Validity of server's certificate (end time), - }) - - for prefix, dn in [("I", cert.get_issuer()), - ("S", cert.get_subject())]: - # X509Name objects don't seem to have a way to get the - # complete DN string. Use str() and slice it instead, - # because str(dn) == "<X509Name object '/C=US/ST=...'>" - dnstr = str(dn)[18:-2] - - wsgikey = 'SSL_SERVER_%s_DN' % prefix - ssl_environ[wsgikey] = dnstr - - # The DN should be of the form: /k1=v1/k2=v2, but we must allow - # for any value to contain slashes itself (in a URL). - while dnstr: - pos = dnstr.rfind("=") - dnstr, value = dnstr[:pos], dnstr[pos + 1:] - pos = dnstr.rfind("/") - dnstr, key = dnstr[:pos], dnstr[pos + 1:] - if key and value: - wsgikey = 'SSL_SERVER_%s_DN_%s' % (prefix, key) - ssl_environ[wsgikey] = value - - self.environ.update(ssl_environ) + if isinstance(req.server.bind_addr, basestring): + # AF_UNIX. This isn't really allowed by WSGI, which doesn't + # address unix domain sockets. But it's better than nothing. + env["SERVER_PORT"] = "" + else: + env["SERVER_PORT"] = str(req.server.bind_addr[1]) + + # Request headers + for k, v in req.inheaders.iteritems(): + env["HTTP_" + k.upper().replace("-", "_")] = v + + # CONTENT_TYPE/CONTENT_LENGTH + ct = env.pop("HTTP_CONTENT_TYPE", None) + if ct is not None: + env["CONTENT_TYPE"] = ct + cl = env.pop("HTTP_CONTENT_LENGTH", None) + if cl is not None: + env["CONTENT_LENGTH"] = cl + + if req.conn.ssl_env: + env.update(req.conn.ssl_env) + + return env + +class WSGIGateway_u0(WSGIGateway_10): + """A Gateway class to interface HTTPServer with WSGI u.0. + + WSGI u.0 is an experimental protocol, which uses unicode for keys and values + in both Python 2 and Python 3. + """ + + def get_environ(self): + """Return a new environ dict targeting the given wsgi.version""" + req = self.req + env_10 = WSGIGateway_10.get_environ(self) + env = dict([(k.decode('ISO-8859-1'), v) for k, v in env_10.iteritems()]) + env[u'wsgi.version'] = ('u', 0) + + # Request-URI + env.setdefault(u'wsgi.url_encoding', u'utf-8') + try: + for key in [u"PATH_INFO", u"SCRIPT_NAME", u"QUERY_STRING"]: + env[key] = env_10[str(key)].decode(env[u'wsgi.url_encoding']) + except UnicodeDecodeError: + # Fall back to latin 1 so apps can transcode if needed. + env[u'wsgi.url_encoding'] = u'ISO-8859-1' + for key in [u"PATH_INFO", u"SCRIPT_NAME", u"QUERY_STRING"]: + env[key] = env_10[str(key)].decode(env[u'wsgi.url_encoding']) + + for k, v in sorted(env.items()): + if isinstance(v, str) and k not in ('REQUEST_URI', 'wsgi.input'): + env[k] = v.decode('ISO-8859-1') + + return env + +wsgi_gateways = { + (1, 0): WSGIGateway_10, + ('u', 0): WSGIGateway_u0, +} + +class WSGIPathInfoDispatcher(object): + """A WSGI dispatcher for dispatch based on the PATH_INFO. + + apps: a dict or list of (path_prefix, app) pairs. + """ + + def __init__(self, apps): + try: + apps = list(apps.items()) + except AttributeError: + pass + + # Sort the apps by len(path), descending + apps.sort(cmp=lambda x,y: cmp(len(x[0]), len(y[0]))) + apps.reverse() + + # The path_prefix strings must start, but not end, with a slash. + # Use "" instead of "/". + self.apps = [(p.rstrip("/"), a) for p, a in apps] + + def __call__(self, environ, start_response): + path = environ["PATH_INFO"] or "/" + for p, app in self.apps: + # The apps list should be sorted by length, descending. + if path.startswith(p + "/") or path == p: + environ = environ.copy() + environ["SCRIPT_NAME"] = environ["SCRIPT_NAME"] + p + environ["PATH_INFO"] = path[len(p):] + return app(environ, start_response) + + start_response('404 Not Found', [('Content-Type', 'text/plain'), + ('Content-Length', '0')]) + return [''] diff --git a/module/network/Browser.py b/module/network/Browser.py index d68a23687..e78d24688 100644 --- a/module/network/Browser.py +++ b/module/network/Browser.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- from logging import getLogger @@ -131,16 +130,3 @@ class Browser(object): del self.dl if hasattr(self, "cj"): del self.cj - -if __name__ == "__main__": - browser = Browser()#proxies={"socks5": "localhost:5000"}) - ip = "http://www.whatismyip.com/automation/n09230945.asp" - #browser.getPage("http://google.com/search?q=bar") - #browser.getPage("https://encrypted.google.com/") - #print browser.getPage(ip) - #print browser.getRedirectLocation("http://google.com/") - #browser.getPage("https://encrypted.google.com/") - #browser.getPage("http://google.com/search?q=bar") - - browser.httpDownload("http://speedtest.netcologne.de/test_10mb.bin", "test_10mb.bin") - diff --git a/module/network/Bucket.py b/module/network/Bucket.py index 69da277ae..a096d644a 100644 --- a/module/network/Bucket.py +++ b/module/network/Bucket.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -13,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: RaNaN """ @@ -47,7 +46,7 @@ class Bucket: time = -self.tokens/float(self.rate) else: time = 0 - + self.lock.release() return time @@ -58,4 +57,3 @@ class Bucket: delta = self.rate * (now - self.timestamp) self.tokens = min(self.rate, self.tokens + delta) self.timestamp = now - diff --git a/module/network/CookieJar.py b/module/network/CookieJar.py index c05812334..a6ae090bc 100644 --- a/module/network/CookieJar.py +++ b/module/network/CookieJar.py @@ -19,7 +19,7 @@ from time import time -class CookieJar(): +class CookieJar: def __init__(self, pluginname, account=None): self.cookies = {} self.plugin = pluginname diff --git a/module/network/HTTPChunk.py b/module/network/HTTPChunk.py index b637aef32..719c3ed0b 100644 --- a/module/network/HTTPChunk.py +++ b/module/network/HTTPChunk.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -13,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: RaNaN """ from os import remove, stat, fsync @@ -30,7 +29,7 @@ class WrongFormat(Exception): pass -class ChunkInfo(): +class ChunkInfo: def __init__(self, name): self.name = unicode(name) self.size = 0 @@ -208,7 +207,7 @@ class HTTPChunk(HTTPRequest): # as first chunk, we will parse the headers if not self.range and self.header.endswith("\r\n\r\n"): self.parseHeader() - elif not self.range and buf.startswith("150") and "data connection" in buf: #ftp file size parsing + elif not self.range and buf.startswith("150") and "data connection" in buf.lower(): #: ftp file size parsing size = search(r"(\d+) bytes", buf) if size: self.p.size = int(size.group(1)) @@ -269,7 +268,7 @@ class HTTPChunk(HTTPRequest): def stop(self): """The download will not proceed after next call of writeBody""" - self.range = [0,0] + self.range = [0, 0] self.size = 0 def resetRange(self): @@ -290,4 +289,4 @@ class HTTPChunk(HTTPRequest): """ closes everything, unusable after this """ if self.fp: self.fp.close() self.c.close() - if hasattr(self, "p"): del self.p
\ No newline at end of file + if hasattr(self, "p"): del self.p diff --git a/module/network/HTTPDownload.py b/module/network/HTTPDownload.py index fe8075539..20ac00e48 100644 --- a/module/network/HTTPDownload.py +++ b/module/network/HTTPDownload.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -13,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: RaNaN """ @@ -29,9 +28,9 @@ from HTTPChunk import ChunkInfo, HTTPChunk from HTTPRequest import BadHeader from module.plugins.Plugin import Abort -from module.utils import save_join, fs_encode +from module.utils import safe_join, fs_encode -class HTTPDownload(): +class HTTPDownload: """ loads a url http + ftp """ def __init__(self, url, filename, get={}, post={}, referer=None, cj=None, bucket=None, @@ -114,7 +113,7 @@ class HTTPDownload(): fo.close() if self.nameDisposition and self.disposition: - self.filename = save_join(dirname(self.filename), self.nameDisposition) + self.filename = safe_join(dirname(self.filename), self.nameDisposition) move(init, fs_encode(self.filename)) self.info.remove() #remove info file @@ -286,7 +285,7 @@ class HTTPDownload(): if self.abort: raise Abort() - #sleep(0.003) #supress busy waiting - limits dl speed to (1 / x) * buffersize + #sleep(0.003) #supress busy waiting - limits dl speed to (1 / x) * buffersize self.m.select(1) for chunk in self.chunks: @@ -324,17 +323,3 @@ class HTTPDownload(): del self.cj if hasattr(self, "info"): del self.info - -if __name__ == "__main__": - url = "http://speedtest.netcologne.de/test_100mb.bin" - - from Bucket import Bucket - - bucket = Bucket() - bucket.setRate(200 * 1024) - bucket = None - - print "starting" - - dwnld = HTTPDownload(url, "test_100mb.bin", bucket=bucket) - dwnld.download(chunks=3, resume=True) diff --git a/module/network/HTTPRequest.py b/module/network/HTTPRequest.py index 4747d937f..67635f944 100644 --- a/module/network/HTTPRequest.py +++ b/module/network/HTTPRequest.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -13,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: RaNaN """ @@ -29,7 +28,7 @@ from module.plugins.Plugin import Abort def myquote(url): return quote(url.encode('utf_8') if isinstance(url, unicode) else url, safe="%/:=&?~#+!$,;'@()*[]") - + def myurlencode(data): data = dict(data) return urlencode(dict((x.encode('utf_8') if isinstance(x, unicode) else x, \ @@ -44,7 +43,7 @@ class BadHeader(Exception): self.content = content -class HTTPRequest(): +class HTTPRequest: def __init__(self, cookies=None, options=None): self.c = pycurl.Curl() self.rep = StringIO() @@ -89,8 +88,8 @@ class HTTPRequest(): if pycurl.version_info()[7]: self.c.setopt(pycurl.ENCODING, "gzip, deflate") self.c.setopt(pycurl.HTTPHEADER, ["Accept: */*", - "Accept-Language: en-US,en", - "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Accept-Language: en-US, en", + "Accept-Charset: ISO-8859-1, utf-8;q=0.7,*;q=0.7", "Connection: keep-alive", "Keep-Alive: 300", "Expect:"]) @@ -193,6 +192,10 @@ class HTTPRequest(): if just_header: self.c.setopt(pycurl.FOLLOWLOCATION, 0) self.c.setopt(pycurl.NOBODY, 1) + if post: + self.c.setopt(pycurl.POST, 1) + else: + self.c.setopt(pycurl.HTTPGET, 1) self.c.perform() rep = self.header @@ -255,7 +258,7 @@ class HTTPRequest(): #self.log.debug("Decoded %s" % encoding ) if lookup(encoding).name == 'utf-8' and rep.startswith(BOM_UTF8): encoding = 'utf-8-sig' - + decoder = getincrementaldecoder(encoding)("replace") rep = decoder.decode(rep, True) @@ -298,9 +301,3 @@ class HTTPRequest(): if hasattr(self, "c"): self.c.close() del self.c - -if __name__ == "__main__": - url = "http://pyload.org" - c = HTTPRequest() - print c.load(url) - diff --git a/module/network/RequestFactory.py b/module/network/RequestFactory.py index 5b1528281..6811b11d8 100644 --- a/module/network/RequestFactory.py +++ b/module/network/RequestFactory.py @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: mkaay, RaNaN """ @@ -26,7 +26,7 @@ from CookieJar import CookieJar from XDCCRequest import XDCCRequest -class RequestFactory(): +class RequestFactory: def __init__(self, core): self.lock = Lock() self.core = core @@ -67,7 +67,7 @@ class RequestFactory(): rep = h.load(*args, **kwargs) finally: h.close() - + return rep def getCookieJar(self, pluginName, account=None): diff --git a/module/network/XDCCRequest.py b/module/network/XDCCRequest.py index f03798c17..74769da96 100644 --- a/module/network/XDCCRequest.py +++ b/module/network/XDCCRequest.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -13,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. - + @author: jeix """ @@ -31,19 +30,18 @@ from select import select from module.plugins.Plugin import Abort -class XDCCRequest(): +class XDCCRequest: def __init__(self, timeout=30, proxies={}): - + self.proxies = proxies self.timeout = timeout - + self.filesize = 0 self.recv = 0 self.speed = 0 - + self.abort = False - def createSocket(self): # proxytype = None # proxy = None @@ -60,33 +58,33 @@ class XDCCRequest(): # else: # sock = socket.socket() # return sock - + return socket.socket() - + def download(self, ip, port, filename, irc, progressNotify=None): ircbuffer = "" lastUpdate = time() cumRecvLen = 0 - + dccsock = self.createSocket() - + dccsock.settimeout(self.timeout) dccsock.connect((ip, port)) - + if exists(filename): i = 0 nameParts = filename.rpartition(".") while True: newfilename = "%s-%d%s%s" % (nameParts[0], i, nameParts[1], nameParts[2]) i += 1 - + if not exists(newfilename): filename = newfilename break - + fh = open(filename, "wb") - + # recv loop for dcc socket while True: if self.abort: @@ -94,44 +92,43 @@ class XDCCRequest(): fh.close() remove(filename) raise Abort() - + self._keepAlive(irc, ircbuffer) - + data = dccsock.recv(4096) dataLen = len(data) self.recv += dataLen - + cumRecvLen += dataLen - + now = time() timespan = now - lastUpdate if timespan > 1: self.speed = cumRecvLen / timespan cumRecvLen = 0 lastUpdate = now - + if progressNotify: progressNotify(self.percent) - - + if not data: break - + fh.write(data) - + # acknowledge data by sending number of recceived bytes dccsock.send(struct.pack('!I', self.recv)) - + dccsock.close() fh.close() - + return filename - + def _keepAlive(self, sock, readbuffer): fdset = select([sock], [], [], 0) if sock not in fdset[0]: return - + readbuffer += sock.recv(1024) temp = readbuffer.split("\n") readbuffer = temp.pop() @@ -144,7 +141,7 @@ class XDCCRequest(): def abortDownloads(self): self.abort = True - + @property def size(self): return self.filesize diff --git a/module/plugins/AccountManager.py b/module/plugins/AccountManager.py index 4b8063002..6c908738c 100644 --- a/module/plugins/AccountManager.py +++ b/module/plugins/AccountManager.py @@ -11,10 +11,10 @@ from module.utils import chmod, lock ACC_VERSION = 1 -class AccountManager(): +class AccountManager: """manages all accounts""" - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def __init__(self, core): """Constructor""" @@ -35,7 +35,10 @@ class AccountManager(): """get account instance for plugin or None if anonymous""" if plugin in self.accounts: if plugin not in self.plugins: - self.plugins[plugin] = self.core.pluginManager.loadClass("accounts", plugin)(self, self.accounts[plugin]) + try: + self.plugins[plugin] = self.core.pluginManager.loadClass("accounts", plugin)(self, self.accounts[plugin]) + except TypeError: # The account class no longer exists (blacklisted plugin). Skipping the account to avoid crash + return None return self.plugins[plugin] else: @@ -50,7 +53,7 @@ class AccountManager(): return plugins - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def loadAccounts(self): """loads all accounts available""" @@ -97,7 +100,7 @@ class AccountManager(): name, sep, pw = line.partition(":") self.accounts[plugin][name] = {"password": pw, "options": {}, "valid": True} - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def saveAccounts(self): """save all account information""" @@ -117,7 +120,7 @@ class AccountManager(): f.close() chmod(f.name, 0600) - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def initAccountPlugins(self): """init names""" for name in self.core.pluginManager.getAccountPlugins(): @@ -155,7 +158,10 @@ class AccountManager(): for p in self.accounts.keys(): if self.accounts[p]: p = self.getAccountPlugin(p) - data[p.__name__] = p.getAllAccounts(force) + if p: + data[p.__name__] = p.getAllAccounts(force) + else: # When an account has been skipped, p is None + data[p] = [] else: data[p] = [] e = AccountUpdateEvent() diff --git a/module/plugins/Crypter.py b/module/plugins/Crypter.py index 74ae8d102..b127777e7 100644 --- a/module/plugins/Crypter.py +++ b/module/plugins/Crypter.py @@ -45,14 +45,20 @@ class Crypter(Plugin): """ create new packages from self.packages """ for pack in self.packages: - self.log.debug("Parsed package %(name)s with %(len)d links" % { "name" : pack[0], "len" : len(pack[1]) } ) + name, links, folder = pack - links = [x.decode("utf-8") for x in pack[1]] + self.logDebug("Parsed package %(name)s with %(len)d links" % {"name": name, "len": len(links)}) - pid = self.core.api.addPackage(pack[0], links, self.pyfile.package().queue) + links = [x.decode("utf-8") for x in links] + + pid = self.api.addPackage(name, links, self.pyfile.package().queue) + + if name != folder is not None: + self.api.setPackageData(pid, {"folder": folder}) #: Due to not break API addPackage method right now + self.logDebug("Set package %(name)s folder to %(folder)s" % {"name": name, "folder": folder}) if self.pyfile.package().password: - self.core.api.setPackageData(pid, {"password": self.pyfile.package().password}) + self.api.setPackageData(pid, {"password": self.pyfile.package().password}) if self.urls: - self.core.api.generateAndAddPackages(self.urls) + self.api.generateAndAddPackages(self.urls) diff --git a/module/plugins/Hook.py b/module/plugins/Hook.py index 279f813d1..e72ab7ebb 100644 --- a/module/plugins/Hook.py +++ b/module/plugins/Hook.py @@ -28,7 +28,6 @@ class Hook(Base): __type__ = "hook" __version__ = "0.2" - __threaded__ = [] __config__ = [("name", "type", "desc", "default")] __description__ = """Interface for hook""" @@ -76,8 +75,9 @@ class Hook(Base): self.event_list = None - self.initPeriodical() self.setup() + self.initPeriodical() + def initPeriodical(self): if self.interval >=1: @@ -87,7 +87,7 @@ class Hook(Base): try: if self.isActivated(): self.periodical() except Exception, e: - self.core.log.error(_("Error executing hooks: %s") % str(e)) + self.logError(_("Error executing hooks: %s") % str(e)) if self.core.debug: print_exc() diff --git a/module/plugins/captcha/captcha.py b/module/plugins/OCR.py index cc07f50cf..0991184f3 100644 --- a/module/plugins/captcha/captcha.py +++ b/module/plugins/OCR.py @@ -1,18 +1,16 @@ # -*- coding: utf-8 -*- from __future__ import with_statement - -import GifImagePlugin -import Image -import JpegImagePlugin -import PngImagePlugin -import TiffImagePlugin -import logging import os +import logging import subprocess -#import tempfile from os.path import abspath, join +from PIL import Image +from PIL import TiffImagePlugin +from PIL import PngImagePlugin +from PIL import GifImagePlugin +from PIL import JpegImagePlugin class OCR(object): @@ -43,16 +41,15 @@ class OCR(object): def run(self, command): """Run a command""" - popen = subprocess.Popen(command, bufsize = -1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + popen = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) popen.wait() - output = popen.stdout.read() +" | "+ popen.stderr.read() + output = popen.stdout.read() + " | " + popen.stderr.read() popen.stdout.close() popen.stderr.close() self.logger.debug("Tesseract ReturnCode %s Output: %s" % (popen.returncode, output)) def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True): #self.logger.debug("create tmp tif") - #tmp = tempfile.NamedTemporaryFile(suffix=".tif") tmp = open(join("tmp", "tmpTif_%s.tif" % self.__name__), "wb") tmp.close() @@ -67,9 +64,9 @@ class OCR(object): if os.name == "nt": tessparams = [join(pypath, "tesseract", "tesseract.exe")] else: - tessparams = ["tesseract"] + tessparams = ['tesseract'] - tessparams.extend( [abspath(tmp.name), abspath(tmpTxt.name).replace(".txt", "")] ) + tessparams.extend([abspath(tmp.name), abspath(tmpTxt.name).replace(".txt", "")]) if subset and (digits or lowercase or uppercase): #self.logger.debug("create temp subset config") @@ -138,11 +135,11 @@ class OCR(object): count = 0 try: - if pixels[x-1, y-1] != 255: + if pixels[x - 1, y - 1] != 255: count += 1 - if pixels[x-1, y] != 255: + if pixels[x - 1, y] != 255: count += 1 - if pixels[x-1, y + 1] != 255: + if pixels[x - 1, y + 1] != 255: count += 1 if pixels[x, y + 1] != 255: count += 1 @@ -150,19 +147,19 @@ class OCR(object): count += 1 if pixels[x + 1, y] != 255: count += 1 - if pixels[x + 1, y-1] != 255: + if pixels[x + 1, y - 1] != 255: count += 1 - if pixels[x, y-1] != 255: + if pixels[x, y - 1] != 255: count += 1 except: pass - # not enough neighbors are dark pixels so mark this pixel - # to be changed to white + # not enough neighbors are dark pixels so mark this pixel + # to be changed to white if count < allowed: pixels[x, y] = 1 - # second pass: this time set all 1's to 255 (white) + # second pass: this time set all 1's to 255 (white) for x in xrange(w): for y in xrange(h): if pixels[x, y] == 1: @@ -197,7 +194,6 @@ class OCR(object): if pixels[x, y] == 0: pixels[x, y] = 255 - count = {} for x in xrange(w): diff --git a/module/plugins/Plugin.py b/module/plugins/Plugin.py index 68b2311b3..8a2554ea0 100644 --- a/module/plugins/Plugin.py +++ b/module/plugins/Plugin.py @@ -14,8 +14,7 @@ if os.name != "nt": from itertools import islice -from module.utils import save_join, save_path, fs_encode, fs_decode - +from module.utils import safe_join, safe_path, fs_encode, fs_decode def chunks(iterable, size): it = iter(iterable) @@ -74,7 +73,7 @@ class Base(object): def setConf(self, option, value): """ see `setConfig` """ - self.core.config.setPlugin(self.__name__, option, value) + self.config.setPlugin(self.__name__, option, value) def setConfig(self, option, value): """ Set config value for current plugin @@ -85,9 +84,10 @@ class Base(object): """ self.setConf(option, value) + #: Deprecated method def getConf(self, option): """ see `getConfig` """ - return self.core.config.getPlugin(self.__name__, option) + return self.getConfig(option) def getConfig(self, option): """ Returns config value for current plugin @@ -95,7 +95,7 @@ class Base(object): :param option: :return: """ - return self.getConf(option) + return self.config.getPlugin(self.__name__, option) def setStorage(self, key, value): """ Saves a value persistently to the database """ @@ -127,7 +127,7 @@ class Plugin(Base): """ __name__ = "Plugin" __type__ = "hoster" - __version__ = "0.4" + __version__ = "0.5" __pattern__ = None __config__ = [("name", "type", "desc", "default")] @@ -140,10 +140,13 @@ class Plugin(Base): def __init__(self, pyfile): Base.__init__(self, pyfile.m.core) + #: engage wan reconnection self.wantReconnect = False - #: enables simultaneous processing of multiple downloads + + #: enable simultaneous processing of multiple downloads self.multiDL = True self.limitDL = 0 + #: chunk limit self.chunkLimit = 1 self.resumeDownload = False @@ -152,7 +155,9 @@ class Plugin(Base): self.waitUntil = 0 self.waiting = False - self.ocr = None #captcha reader instance + #: captcha reader instance + self.ocr = None + #: account handler instance, see :py:class:`Account` self.account = pyfile.m.core.accountManager.getAccountPlugin(self.__name__) @@ -161,7 +166,9 @@ class Plugin(Base): #: username/login self.user = None - if self.account and not self.account.canUse(): self.account = None + if self.account and not self.account.canUse(): + self.account = None + if self.account: self.user, data = self.account.selectAccount() #: Browser instance, see `network.Browser` @@ -177,18 +184,28 @@ class Plugin(Base): #: associated pyfile instance, see `PyFile` self.pyfile = pyfile + self.thread = None # holds thread in future #: location where the last call to download was saved self.lastDownload = "" #: re match of the last call to `checkDownload` self.lastCheck = None + #: js engine, see `JsEngine` self.js = self.core.js - self.cTask = None #captcha task - self.retries = 0 # amount of retries already made - self.html = None # some plugins store html code here + #: captcha task + self.cTask = None + + #: amount of retries already made + self.retries = 0 + + #: some plugins store html code here + self.html = None + + #: quick caller for API + self.api = self.core.api self.init() @@ -248,7 +265,7 @@ class Plugin(Base): return True, 10 - def setWait(self, seconds, reconnect=False): + def setWait(self, seconds, reconnect=None): """Set a specific wait time later used with `wait` :param seconds: wait time in seconds @@ -258,15 +275,23 @@ class Plugin(Base): self.wantReconnect = True self.pyfile.waitUntil = time() + int(seconds) - def wait(self): - """ waits the time previously set """ + def wait(self, seconds=None, reconnect=None): + """ Waits the time previously set or use these from arguments. See `setWait` + """ + if seconds: + self.setWait(seconds, reconnect) + + self._wait() + + def _wait(self): self.waiting = True self.pyfile.setStatus("waiting") while self.pyfile.waitUntil > time(): self.thread.m.reconnecting.wait(2) - if self.pyfile.abort: raise Abort + if self.pyfile.abort: + raise Abort if self.thread.m.reconnecting.isSet(): self.waiting = False self.wantReconnect = False @@ -372,7 +397,7 @@ class Plugin(Base): self.fail(_("No captcha result obtained in appropiate time by any of the plugins.")) result = task.result - self.log.debug("Received captcha result: %s" % str(result)) + self.logDebug("Received captcha result: %s" % str(result)) if not self.core.debug: try: @@ -462,23 +487,23 @@ class Plugin(Base): download_folder = self.config['general']['download_folder'] - location = save_join(download_folder, self.pyfile.package().folder) + location = safe_join(download_folder, self.pyfile.package().folder) if not exists(location): - makedirs(location, int(self.core.config['permission']['folder'], 8)) + makedirs(location, int(self.config['permission']['folder'], 8)) - if self.core.config['permission']['change_dl'] and os.name != "nt": + if self.config['permission']['change_dl'] and os.name != "nt": try: uid = getpwnam(self.config['permission']['user'])[2] gid = getgrnam(self.config['permission']['group'])[2] chown(location, uid, gid) except Exception, e: - self.log.warning(_("Setting User and Group failed: %s") % str(e)) + self.logWarning(_("Setting User and Group failed: %s") % str(e)) # convert back to unicode location = fs_decode(location) - name = save_path(self.pyfile.name) + name = safe_path(self.pyfile.name) filename = join(location, name) @@ -492,23 +517,23 @@ class Plugin(Base): self.pyfile.size = self.req.size if disposition and newname and newname != name: #triple check, just to be sure - self.log.info("%(name)s saved as %(newname)s" % {"name": name, "newname": newname}) + self.logInfo("%(name)s saved as %(newname)s" % {"name": name, "newname": newname}) self.pyfile.name = newname filename = join(location, newname) fs_filename = fs_encode(filename) - if self.core.config['permission']['change_file']: - chmod(fs_filename, int(self.core.config['permission']['file'], 8)) + if self.config['permission']['change_file']: + chmod(fs_filename, int(self.config['permission']['file'], 8)) - if self.core.config['permission']['change_dl'] and os.name != "nt": + if self.config['permission']['change_dl'] and os.name != "nt": try: uid = getpwnam(self.config['permission']['user'])[2] gid = getgrnam(self.config['permission']['group'])[2] chown(fs_filename, uid, gid) except Exception, e: - self.log.warning(_("Setting User and Group failed: %s") % str(e)) + self.logWarning(_("Setting User and Group failed: %s") % str(e)) self.lastDownload = filename return self.lastDownload @@ -531,12 +556,12 @@ class Plugin(Base): if api_size and api_size <= size: return None elif size > max_size and not read_size: return None - self.log.debug("Download Check triggered") + self.logDebug("Download Check triggered") f = open(lastDownload, "rb") content = f.read(read_size if read_size else -1) f.close() #produces encoding errors, better log to other file in the future? - #self.log.debug("Content: %s" % content) + #self.logDebug("Content: %s" % content) for name, rule in rules.iteritems(): if type(rule) in (str, unicode): if rule in content: @@ -577,9 +602,9 @@ class Plugin(Base): raise SkipDownload(pyfile.pluginname) download_folder = self.config['general']['download_folder'] - location = save_join(download_folder, pack.folder, self.pyfile.name) + location = safe_join(download_folder, pack.folder, self.pyfile.name) - if starting and self.core.config['download']['skip_existing'] and exists(location): + if starting and self.config['download']['skip_existing'] and exists(location): size = os.stat(location).st_size if size >= self.pyfile.size: raise SkipDownload("File exists.") @@ -589,7 +614,7 @@ class Plugin(Base): if exists(location): raise SkipDownload(pyfile[0]) - self.log.debug("File %s not skipped, because it does not exists." % self.pyfile.name) + self.logDebug("File %s not skipped, because it does not exists." % self.pyfile.name) def clean(self): """ clean everything and remove references """ diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 9c7cab64c..32ea4d16b 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -17,7 +17,7 @@ from module.ConfigParser import IGNORE class PluginManager: ROOT = "module.plugins." USERROOT = "userplugins." - TYPES = ("crypter", "container", "hoster", "captcha", "accounts", "hooks", "internal") + TYPES = ("accounts", "container", "crypter", "hooks", "hoster", "internal", "ocr") PATTERN = re.compile(r'__pattern__.*=.*r("|\')([^"\']+)') VERSION = re.compile(r'__version__.*=.*("|\')([0-9.]+)') @@ -28,7 +28,7 @@ class PluginManager: def __init__(self, core): self.core = core - #self.config = self.core.config + self.config = core.config self.log = core.log self.plugins = {} @@ -53,7 +53,7 @@ class PluginManager: self.plugins['container'] = self.containerPlugins = self.parse("container", pattern=True) self.plugins['hoster'] = self.hosterPlugins = self.parse("hoster", pattern=True) - self.plugins['captcha'] = self.captchaPlugins = self.parse("captcha") + self.plugins['ocr'] = self.captchaPlugins = self.parse("ocr") self.plugins['accounts'] = self.accountPlugins = self.parse("accounts") self.plugins['hooks'] = self.hookPlugins = self.parse("hooks") self.plugins['internal'] = self.internalPlugins = self.parse("internal") @@ -140,7 +140,7 @@ class PluginManager: # internals have no config if folder == "internal": - self.core.config.deleteConfig(name) + self.config.deleteConfig(name) continue config = self.CONFIG.findall(content) @@ -163,7 +163,7 @@ class PluginManager: if append: config.append(["activated", "bool", "Activated", False]) try: - self.core.config.addPluginConfig(name, config, desc) + self.config.addPluginConfig(name, config, desc) except: self.log.error("Invalid config in %s: %s" % (name, config)) @@ -173,7 +173,7 @@ class PluginManager: config = (["activated", "bool", "Activated", False],) try: - self.core.config.addPluginConfig(name, config, desc) + self.config.addPluginConfig(name, config, desc) except: self.log.error("Invalid config in %s: %s" % (name, config)) @@ -308,57 +308,49 @@ class PluginManager: def reloadPlugins(self, type_plugins): - """ reloads and reindexes plugins """ - if not type_plugins: return False + """ reload and reindex plugins """ + if not type_plugins: + return None self.log.debug("Request reload of plugins: %s" % type_plugins) + reloaded = [] + as_dict = {} for t,n in type_plugins: - if t in as_dict: + if t in ("hooks", "internal"): #: do not reload hooks or internals, because would cause to much side effects + continue + elif t in as_dict: as_dict[t].append(n) else: as_dict[t] = [n] - # we do not reload hooks or internals, would cause to much side effects - if "hooks" in as_dict or "internal" in as_dict: - return False - for type in as_dict.iterkeys(): for plugin in as_dict[type]: - if plugin in self.plugins[type]: - if "module" in self.plugins[type][plugin]: - self.log.debug("Reloading %s" % plugin) + if plugin in self.plugins[type] and "module" in self.plugins[type][plugin]: + self.log.debug("Reloading %s" % plugin) + id = (type, plugin) + try: reload(self.plugins[type][plugin]['module']) + except Exception, e: + self.log.error("Error when reloading %s" % id, str(e)) + continue + else: + reloaded.append(id) #index creation self.plugins['crypter'] = self.crypterPlugins = self.parse("crypter", pattern=True) self.plugins['container'] = self.containerPlugins = self.parse("container", pattern=True) self.plugins['hoster'] = self.hosterPlugins = self.parse("hoster", pattern=True) - self.plugins['captcha'] = self.captchaPlugins = self.parse("captcha") + self.plugins['ocr'] = self.captchaPlugins = self.parse("ocr") self.plugins['accounts'] = self.accountPlugins = self.parse("accounts") - if "accounts" in as_dict: #accounts needs to be reloaded + if "accounts" in as_dict: #: accounts needs to be reloaded self.core.accountManager.initPlugins() self.core.scheduler.addJob(0, self.core.accountManager.getAccountInfos) - return True - - - -if __name__ == "__main__": - _ = lambda x: x - pypath = "/home/christian/Projekte/pyload-0.4/module/plugins" - - from time import time - - p = PluginManager(None) - - a = time() - - test = ["http://www.youtube.com/watch?v=%s" % x for x in xrange(0, 100)] - print p.parseUrls(test) - - b = time() + return reloaded #: return a list of the plugins successfully reloaded - print b - a, "s" + def reloadPlugin(self, type_plugin): + """ reload and reindex ONE plugin """ + return True if self.reloadPlugins(type_plugin) else False diff --git a/module/plugins/README.md b/module/plugins/README.md new file mode 100644 index 000000000..fa2a4c5b2 --- /dev/null +++ b/module/plugins/README.md @@ -0,0 +1,16 @@ +Licensing +--------- + +According to the terms of the GNU General Public License, +pyload's plugins must be treated as an extension of the main program. +This means the plugins must be released under the GPL or a GPL-compatible +free software license, and that the terms of the GPL must be followed when +those plugins are distributed. + + * Any plugin published **without a license notice** is intend published under the **GNU GPLv3**. + * A different license can be used but it **must be GPL-compatible** and the license notice must be put in the plugin + file. + * Any plugin published **with a GPL incompatible license** will be rejected. + This includes *copyright all right reserved*. + * Is recommended to put the license notice at the top of the plugin file. + * Is recommended to **not** put the license notice when plugin is published under the GNU GPLv3. diff --git a/module/plugins/ReCaptcha.py b/module/plugins/ReCaptcha.py deleted file mode 100644 index 143ecfb83..000000000 --- a/module/plugins/ReCaptcha.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - - -class ReCaptcha(): - - def __init__(self, plugin): - self.plugin = plugin - - def challenge(self, id): - js = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={"k":id}, cookies=True) - - try: - challenge = re.search("challenge : '(.*?)',", js).group(1) - server = re.search("server : '(.*?)',", js).group(1) - except: - self.plugin.fail("recaptcha error") - result = self.result(server,challenge) - - return challenge, result - - def result(self, server, challenge): - return self.plugin.decryptCaptcha("%simage"%server, get={"c":challenge}, cookies=True, imgtype="jpg") diff --git a/module/plugins/accounts/Ftp.py b/module/plugins/accounts/Ftp.py index 2e60874a9..1319ea2a7 100644 --- a/module/plugins/accounts/Ftp.py +++ b/module/plugins/accounts/Ftp.py @@ -13,4 +13,4 @@ class Ftp(Account): __author_mail__ = "zoidberg@mujmail.cz" - login_timeout = info_threshold = 1000000 + login_timeout = info_threshold = -1 #: Unlimited diff --git a/module/plugins/accounts/Http.py b/module/plugins/accounts/Http.py index 3b64fe8da..589a45617 100644 --- a/module/plugins/accounts/Http.py +++ b/module/plugins/accounts/Http.py @@ -13,4 +13,4 @@ class Http(Account): __author_mail__ = "zoidberg@mujmail.cz" - login_timeout = info_threshold = 1000000 + login_timeout = info_threshold = -1 #: Unlimited diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index f6d202ee9..6bcad293c 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -7,8 +7,9 @@ from module.utils import remove_chars class MultiHoster(Hook): - __name__ = "AbtractExtractor" - __version__ = "0.19" + __name__ = "MultiHoster" + __type__ = "hook" + __version__ = "0.20" __description__ = """Generic MultiHoster plugin""" __author_name__ = "pyLoad Team" @@ -28,15 +29,15 @@ class MultiHoster(Hook): self.new_supported = [] def getConfig(self, option, default=''): - """getConfig with default value - sublass may not implements all config options""" + """getConfig with default value - subclass may not implements all config options""" try: - return self.getConf(option) + # Fixed loop due to getConf deprecation in 0.4.10 + return super(MultiHoster, self).getConfig(option) except KeyError: return default def getHosterCached(self): if not self.hosters: - try: hosterSet = self.toHosterSet(self.getHoster()) - set(self.ignored) except Exception, e: diff --git a/module/plugins/captcha/GigasizeCom.py b/module/plugins/ocr/GigasizeCom.py index add3ffc57..ba0b805e6 100644 --- a/module/plugins/captcha/GigasizeCom.py +++ b/module/plugins/ocr/GigasizeCom.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from module.plugins.captcha import OCR +from module.plugins.OCR import OCR class GigasizeCom(OCR): diff --git a/module/plugins/captcha/LinksaveIn.py b/module/plugins/ocr/LinksaveIn.py index dd5ac7b98..3ae139a4e 100644 --- a/module/plugins/captcha/LinksaveIn.py +++ b/module/plugins/ocr/LinksaveIn.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- +from module.plugins.OCR import OCR from PIL import Image -from glob import glob from os import sep from os.path import abspath, dirname - -from module.plugins.captcha import OCR +from glob import glob class LinksaveIn(OCR): diff --git a/module/plugins/captcha/NetloadIn.py b/module/plugins/ocr/NetloadIn.py index cb6cb9264..0de88302e 100644 --- a/module/plugins/captcha/NetloadIn.py +++ b/module/plugins/ocr/NetloadIn.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from module.plugins.captcha import OCR - +from module.plugins.OCR import OCR class NetloadIn(OCR): __name__ = "NetloadIn" diff --git a/module/plugins/captcha/ShareonlineBiz.py b/module/plugins/ocr/ShareonlineBiz.py index aab4e9da0..0ad018bf9 100644 --- a/module/plugins/captcha/ShareonlineBiz.py +++ b/module/plugins/ocr/ShareonlineBiz.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from module.plugins.captcha import OCR +from module.plugins.OCR import OCR class ShareonlineBiz(OCR): diff --git a/module/web/__init__.py b/module/plugins/ocr/__init__.py index e69de29bb..e69de29bb 100644 --- a/module/web/__init__.py +++ b/module/plugins/ocr/__init__.py diff --git a/module/remote/ClickAndLoadBackend.py b/module/remote/ClickAndLoadBackend.py index ad8031587..82167f6e3 100644 --- a/module/remote/ClickAndLoadBackend.py +++ b/module/remote/ClickAndLoadBackend.py @@ -93,7 +93,7 @@ class CNLHandler(BaseHTTPRequestHandler): resp += "\r\n" self.start_response(resp) self.wfile.write(resp) - except Exception,e : + except Exception, e: self.send_error(500, str(e)) else: self.send_error(404, "Not Found") @@ -139,7 +139,7 @@ class CNLHandler(BaseHTTPRequestHandler): IV = Key obj = AES.new(Key, AES.MODE_CBC, IV) - result = obj.decrypt(crypted).replace("\x00", "").replace("\r","").split("\n") + result = obj.decrypt(crypted).replace("\x00", "").replace("\r", "").split("\n") result = filter(lambda x: x != "", result) diff --git a/module/remote/RemoteManager.py b/module/remote/RemoteManager.py index 36eb52a4a..723bc0c0e 100644 --- a/module/remote/RemoteManager.py +++ b/module/remote/RemoteManager.py @@ -55,7 +55,7 @@ class BackendBase(Thread): self.shutdown() -class RemoteManager(): +class RemoteManager: available = [] def __init__(self, core): diff --git a/module/remote/ThriftBackend.py b/module/remote/ThriftBackend.py index b4a2bb25e..f8edc8dd6 100644 --- a/module/remote/ThriftBackend.py +++ b/module/remote/ThriftBackend.py @@ -46,11 +46,11 @@ class ThriftBackend(BackendBase): # tfactory = TransportFactoryCompressed() tfactory = TransportFactory() pfactory = ProtocolFactory() - + self.server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) #self.server = TNonblockingServer.TNonblockingServer(processor, transport, tfactory, pfactory) - + #server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory) - + def serve(self): self.server.serve() diff --git a/module/remote/__init__.py b/module/remote/__init__.py index 9298f5337..60dfa77c7 100644 --- a/module/remote/__init__.py +++ b/module/remote/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- + activated = True diff --git a/module/remote/socketbackend/__init__.py b/module/remote/socketbackend/__init__.py index de6d13128..e69de29bb 100644 --- a/module/remote/socketbackend/__init__.py +++ b/module/remote/socketbackend/__init__.py @@ -1,2 +0,0 @@ -__author__ = 'christian' -
\ No newline at end of file diff --git a/module/remote/socketbackend/create_ttypes.py b/module/remote/socketbackend/create_ttypes.py index 05662cb50..64398c3e7 100644 --- a/module/remote/socketbackend/create_ttypes.py +++ b/module/remote/socketbackend/create_ttypes.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- import inspect @@ -37,8 +36,7 @@ def main(): f = open(join(path, "ttypes.py"), "wb") f.write( - """#!/usr/bin/env python -# -*- coding: utf-8 -*- + """# -*- coding: utf-8 -*- # Autogenerated by pyload # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING @@ -86,6 +84,3 @@ class BaseObject(object): f.write("\n") f.close() - -if __name__ == "__main__": - main()
\ No newline at end of file diff --git a/module/remote/socketbackend/ttypes.py b/module/remote/socketbackend/ttypes.py index f8ea121fa..3fd02fac8 100644 --- a/module/remote/socketbackend/ttypes.py +++ b/module/remote/socketbackend/ttypes.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # Autogenerated by pyload # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING @@ -380,4 +379,3 @@ class Iface: pass def uploadContainer(self, filename, data): pass - diff --git a/module/remote/thriftbackend/Protocol.py b/module/remote/thriftbackend/Protocol.py index c42d01459..a5822df18 100644 --- a/module/remote/thriftbackend/Protocol.py +++ b/module/remote/thriftbackend/Protocol.py @@ -27,4 +27,4 @@ class ProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory): def getProtocol(self, trans): prot = Protocol(trans, self.strictRead, self.strictWrite) - return prot
\ No newline at end of file + return prot diff --git a/module/remote/thriftbackend/Socket.py b/module/remote/thriftbackend/Socket.py index 2243f9df2..b9fa7edbf 100644 --- a/module/remote/thriftbackend/Socket.py +++ b/module/remote/thriftbackend/Socket.py @@ -26,14 +26,14 @@ class SecureSocketConnection: def accept(self): connection, address = self.__dict__["connection"].accept() return SecureSocketConnection(connection), address - + def send(self, buff): try: return self.__dict__["connection"].send(buff) except WantReadError: sleep(0.1) return self.send(buff) - + def recv(self, buff): try: return self.__dict__["connection"].recv(buff) @@ -86,7 +86,7 @@ class Socket(TSocket): buff = '' else: raise - + if not len(buff): raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket read 0 bytes') return buff diff --git a/module/remote/thriftbackend/ThriftClient.py b/module/remote/thriftbackend/ThriftClient.py index 74363cf62..913719ed9 100644 --- a/module/remote/thriftbackend/ThriftClient.py +++ b/module/remote/thriftbackend/ThriftClient.py @@ -85,25 +85,3 @@ class ThriftClient: def __getattr__(self, item): return getattr(self.client, item) - -if __name__ == "__main__": - - client = ThriftClient(user="User", password="pwhere") - - print client.getServerVersion() - print client.statusServer() - print client.statusDownloads() - q = client.getQueue() - -# for p in q: -# data = client.getPackageData(p.pid) -# print data -# print "Package Name: ", data.name - - - print client.getServices() - print client.call(Pyload.ServiceCall("UpdateManager", "recheckForUpdates")) - - print client.getConfigValue("download", "limit_speed", "core") - - client.close()
\ No newline at end of file diff --git a/module/remote/thriftbackend/ThriftTest.py b/module/remote/thriftbackend/ThriftTest.py index 69ac6a745..aec20fa33 100644 --- a/module/remote/thriftbackend/ThriftTest.py +++ b/module/remote/thriftbackend/ThriftTest.py @@ -1,10 +1,9 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- import sys -from os.path import join,abspath,dirname +from os.path import join, abspath, dirname -path = join((abspath(dirname(__file__))), "..","..", "lib") +path = join((abspath(dirname(__file__))), "..", "..", "lib") sys.path.append(path) from thriftgen.pyload import Pyload @@ -22,11 +21,11 @@ import xmlrpclib def bench(f, *args, **kwargs): s = time() - ret = [f(*args, **kwargs) for i in range(0,100)] + ret = [f(*args, **kwargs) for i in range(0, 100)] e = time() try: print "%s: %f s" % (f._Method__name, e-s) - except : + except: print "%s: %f s" % (f.__name__, e-s) return ret diff --git a/module/remote/thriftbackend/Transport.py b/module/remote/thriftbackend/Transport.py index 5772c5a9e..b5b6c8104 100644 --- a/module/remote/thriftbackend/Transport.py +++ b/module/remote/thriftbackend/Transport.py @@ -34,4 +34,4 @@ class TransportFactoryCompressed: ztrans = TransportCompressed(Transport(trans), compresslevel) self._last_trans = trans self._last_z = ztrans - return ztrans
\ No newline at end of file + return ztrans diff --git a/module/remote/thriftbackend/pyload.thrift b/module/remote/thriftbackend/pyload.thrift index 1542e651a..3aef7af00 100644 --- a/module/remote/thriftbackend/pyload.thrift +++ b/module/remote/thriftbackend/pyload.thrift @@ -194,7 +194,7 @@ struct OnlineStatus { 2: PluginName plugin, 3: string packagename, 4: DownloadStatus status, - 5: i64 size, // size <= 0 : unknown + 5: i64 size, // size <= 0: unknown } struct OnlineCheck { @@ -297,13 +297,13 @@ service Pyload { //events list<EventInfo> getEvents(1: string uuid) - + //accounts list<AccountInfo> getAccounts(1: bool refresh), list<string> getAccountTypes() void updateAccount(1: PluginName plugin, 2: string account, 3: string password, 4: map<string, string> options), void removeAccount(1: PluginName plugin, 2: string account), - + //auth bool login(1: string username, 2: string password), UserData getUserData(1: string username, 2:string password), @@ -311,7 +311,7 @@ service Pyload { //services - // servicename : description + // servicename: description map<PluginName, map<string, string>> getServices(), bool hasService(1: PluginName plugin, 2: string func), string call(1: ServiceCall info) throws (1: ServiceDoesNotExists ex, 2: ServiceException e), @@ -319,7 +319,7 @@ service Pyload { //info // {plugin: {name: value}} - map<PluginName, map<string,string>> getAllInfo(), + map<PluginName, map<string, string>> getAllInfo(), map<string, string> getInfoByPlugin(1: PluginName plugin), //scheduler diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote index bfaf5b078..ddc1dd451 100755 --- a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote +++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote @@ -1,10 +1,9 @@ -#!/usr/bin/env python # # Autogenerated by Thrift Compiler (0.9.0-dev) # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # -# options string: py:slots,dynamic +# options string: py:slots, dynamic # import sys @@ -19,9 +18,9 @@ import Pyload from ttypes import * if len(sys.argv) <= 1 or sys.argv[1] == '--help': - print '' + print print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' - print '' + print print 'Functions:' print ' string getConfigValue(string category, string option, string section)' print ' void setConfigValue(string category, string option, string value, string section)' @@ -93,7 +92,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help': print ' CaptchaTask getCaptchaTask(bool exclusive)' print ' string getCaptchaTaskStatus(TaskID tid)' print ' void setCaptchaResult(TaskID tid, string result)' - print '' + print sys.exit(0) pp = pprint.PrettyPrinter(indent = 2) @@ -148,13 +147,13 @@ if cmd == 'getConfigValue': if len(args) != 3: print 'getConfigValue requires 3 args' sys.exit(1) - pp.pprint(client.getConfigValue(args[0],args[1],args[2],)) + pp.pprint(client.getConfigValue(args[0], args[1], args[2],)) elif cmd == 'setConfigValue': if len(args) != 4: print 'setConfigValue requires 4 args' sys.exit(1) - pp.pprint(client.setConfigValue(args[0],args[1],args[2],args[3],)) + pp.pprint(client.setConfigValue(args[0], args[1], args[2], args[3],)) elif cmd == 'getConfig': if len(args) != 0: @@ -256,7 +255,7 @@ elif cmd == 'parseURLs': if len(args) != 2: print 'parseURLs requires 2 args' sys.exit(1) - pp.pprint(client.parseURLs(args[0],args[1],)) + pp.pprint(client.parseURLs(args[0], args[1],)) elif cmd == 'checkOnlineStatus': if len(args) != 1: @@ -268,7 +267,7 @@ elif cmd == 'checkOnlineStatusContainer': if len(args) != 3: print 'checkOnlineStatusContainer requires 3 args' sys.exit(1) - pp.pprint(client.checkOnlineStatusContainer(eval(args[0]),args[1],args[2],)) + pp.pprint(client.checkOnlineStatusContainer(eval(args[0]), args[1], args[2],)) elif cmd == 'pollResults': if len(args) != 1: @@ -340,25 +339,25 @@ elif cmd == 'generateAndAddPackages': if len(args) != 2: print 'generateAndAddPackages requires 2 args' sys.exit(1) - pp.pprint(client.generateAndAddPackages(eval(args[0]),eval(args[1]),)) + pp.pprint(client.generateAndAddPackages(eval(args[0]), eval(args[1]),)) elif cmd == 'addPackage': if len(args) != 3: print 'addPackage requires 3 args' sys.exit(1) - pp.pprint(client.addPackage(args[0],eval(args[1]),eval(args[2]),)) + pp.pprint(client.addPackage(args[0], eval(args[1]), eval(args[2]),)) elif cmd == 'addFiles': if len(args) != 2: print 'addFiles requires 2 args' sys.exit(1) - pp.pprint(client.addFiles(eval(args[0]),eval(args[1]),)) + pp.pprint(client.addFiles(eval(args[0]), eval(args[1]),)) elif cmd == 'uploadContainer': if len(args) != 2: print 'uploadContainer requires 2 args' sys.exit(1) - pp.pprint(client.uploadContainer(args[0],args[1],)) + pp.pprint(client.uploadContainer(args[0], args[1],)) elif cmd == 'deleteFiles': if len(args) != 1: @@ -418,37 +417,37 @@ elif cmd == 'setPackageName': if len(args) != 2: print 'setPackageName requires 2 args' sys.exit(1) - pp.pprint(client.setPackageName(eval(args[0]),args[1],)) + pp.pprint(client.setPackageName(eval(args[0]), args[1],)) elif cmd == 'movePackage': if len(args) != 2: print 'movePackage requires 2 args' sys.exit(1) - pp.pprint(client.movePackage(eval(args[0]),eval(args[1]),)) + pp.pprint(client.movePackage(eval(args[0]), eval(args[1]),)) elif cmd == 'moveFiles': if len(args) != 2: print 'moveFiles requires 2 args' sys.exit(1) - pp.pprint(client.moveFiles(eval(args[0]),eval(args[1]),)) + pp.pprint(client.moveFiles(eval(args[0]), eval(args[1]),)) elif cmd == 'orderPackage': if len(args) != 2: print 'orderPackage requires 2 args' sys.exit(1) - pp.pprint(client.orderPackage(eval(args[0]),eval(args[1]),)) + pp.pprint(client.orderPackage(eval(args[0]), eval(args[1]),)) elif cmd == 'orderFile': if len(args) != 2: print 'orderFile requires 2 args' sys.exit(1) - pp.pprint(client.orderFile(eval(args[0]),eval(args[1]),)) + pp.pprint(client.orderFile(eval(args[0]), eval(args[1]),)) elif cmd == 'setPackageData': if len(args) != 2: print 'setPackageData requires 2 args' sys.exit(1) - pp.pprint(client.setPackageData(eval(args[0]),eval(args[1]),)) + pp.pprint(client.setPackageData(eval(args[0]), eval(args[1]),)) elif cmd == 'deleteFinished': if len(args) != 0: @@ -484,25 +483,25 @@ elif cmd == 'updateAccount': if len(args) != 4: print 'updateAccount requires 4 args' sys.exit(1) - pp.pprint(client.updateAccount(eval(args[0]),args[1],args[2],eval(args[3]),)) + pp.pprint(client.updateAccount(eval(args[0]), args[1], args[2], eval(args[3]),)) elif cmd == 'removeAccount': if len(args) != 2: print 'removeAccount requires 2 args' sys.exit(1) - pp.pprint(client.removeAccount(eval(args[0]),args[1],)) + pp.pprint(client.removeAccount(eval(args[0]), args[1],)) elif cmd == 'login': if len(args) != 2: print 'login requires 2 args' sys.exit(1) - pp.pprint(client.login(args[0],args[1],)) + pp.pprint(client.login(args[0], args[1],)) elif cmd == 'getUserData': if len(args) != 2: print 'getUserData requires 2 args' sys.exit(1) - pp.pprint(client.getUserData(args[0],args[1],)) + pp.pprint(client.getUserData(args[0], args[1],)) elif cmd == 'getAllUserData': if len(args) != 0: @@ -520,7 +519,7 @@ elif cmd == 'hasService': if len(args) != 2: print 'hasService requires 2 args' sys.exit(1) - pp.pprint(client.hasService(eval(args[0]),args[1],)) + pp.pprint(client.hasService(eval(args[0]), args[1],)) elif cmd == 'call': if len(args) != 1: @@ -562,7 +561,7 @@ elif cmd == 'setCaptchaResult': if len(args) != 2: print 'setCaptchaResult requires 2 args' sys.exit(1) - pp.pprint(client.setCaptchaResult(eval(args[0]),args[1],)) + pp.pprint(client.setCaptchaResult(eval(args[0]), args[1],)) else: print 'Unrecognized method %s' % cmd diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py index 78a42f16a..f0b356375 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py +++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py @@ -3,7 +3,7 @@ # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # -# options string: py:slots,dynamic +# options string: py:slots, dynamic # from thrift.Thrift import TType, TMessageType, TException @@ -32,34 +32,34 @@ class Iface(object): """ pass - def getConfig(self, ): + def getConfig(self,): pass - def getPluginConfig(self, ): + def getPluginConfig(self,): pass - def pauseServer(self, ): + def pauseServer(self,): pass - def unpauseServer(self, ): + def unpauseServer(self,): pass - def togglePause(self, ): + def togglePause(self,): pass - def statusServer(self, ): + def statusServer(self,): pass - def freeSpace(self, ): + def freeSpace(self,): pass - def getServerVersion(self, ): + def getServerVersion(self,): pass - def kill(self, ): + def kill(self,): pass - def restart(self, ): + def restart(self,): pass def getLog(self, offset): @@ -69,13 +69,13 @@ class Iface(object): """ pass - def isTimeDownload(self, ): + def isTimeDownload(self,): pass - def isTimeReconnect(self, ): + def isTimeReconnect(self,): pass - def toggleReconnect(self, ): + def toggleReconnect(self,): pass def generatePackages(self, links): @@ -123,7 +123,7 @@ class Iface(object): """ pass - def statusDownloads(self, ): + def statusDownloads(self,): pass def getPackageData(self, pid): @@ -147,16 +147,16 @@ class Iface(object): """ pass - def getQueue(self, ): + def getQueue(self,): pass - def getCollector(self, ): + def getCollector(self,): pass - def getQueueData(self, ): + def getQueueData(self,): pass - def getCollectorData(self, ): + def getCollectorData(self,): pass def getPackageOrder(self, destination): @@ -255,7 +255,7 @@ class Iface(object): """ pass - def stopAllDownloads(self, ): + def stopAllDownloads(self,): pass def stopDownloads(self, fids): @@ -313,10 +313,10 @@ class Iface(object): """ pass - def deleteFinished(self, ): + def deleteFinished(self,): pass - def restartFailed(self, ): + def restartFailed(self,): pass def getEvents(self, uuid): @@ -333,7 +333,7 @@ class Iface(object): """ pass - def getAccountTypes(self, ): + def getAccountTypes(self,): pass def updateAccount(self, plugin, account, password, options): @@ -370,10 +370,10 @@ class Iface(object): """ pass - def getAllUserData(self, ): + def getAllUserData(self,): pass - def getServices(self, ): + def getServices(self,): pass def hasService(self, plugin, func): @@ -391,7 +391,7 @@ class Iface(object): """ pass - def getAllInfo(self, ): + def getAllInfo(self,): pass def getInfoByPlugin(self, plugin): @@ -401,7 +401,7 @@ class Iface(object): """ pass - def isCaptchaWaiting(self, ): + def isCaptchaWaiting(self,): pass def getCaptchaTask(self, exclusive): @@ -454,7 +454,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getConfigValue(self, ): + def recv_getConfigValue(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -490,7 +490,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_setConfigValue(self, ): + def recv_setConfigValue(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -502,18 +502,18 @@ class Client(Iface): self._iprot.readMessageEnd() return - def getConfig(self, ): + def getConfig(self,): self.send_getConfig() return self.recv_getConfig() - def send_getConfig(self, ): + def send_getConfig(self,): self._oprot.writeMessageBegin('getConfig', TMessageType.CALL, self._seqid) args = getConfig_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getConfig(self, ): + def recv_getConfig(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -527,18 +527,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getConfig failed: unknown result"); - def getPluginConfig(self, ): + def getPluginConfig(self,): self.send_getPluginConfig() return self.recv_getPluginConfig() - def send_getPluginConfig(self, ): + def send_getPluginConfig(self,): self._oprot.writeMessageBegin('getPluginConfig', TMessageType.CALL, self._seqid) args = getPluginConfig_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPluginConfig(self, ): + def recv_getPluginConfig(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -552,18 +552,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getPluginConfig failed: unknown result"); - def pauseServer(self, ): + def pauseServer(self,): self.send_pauseServer() self.recv_pauseServer() - def send_pauseServer(self, ): + def send_pauseServer(self,): self._oprot.writeMessageBegin('pauseServer', TMessageType.CALL, self._seqid) args = pauseServer_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_pauseServer(self, ): + def recv_pauseServer(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -575,18 +575,18 @@ class Client(Iface): self._iprot.readMessageEnd() return - def unpauseServer(self, ): + def unpauseServer(self,): self.send_unpauseServer() self.recv_unpauseServer() - def send_unpauseServer(self, ): + def send_unpauseServer(self,): self._oprot.writeMessageBegin('unpauseServer', TMessageType.CALL, self._seqid) args = unpauseServer_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_unpauseServer(self, ): + def recv_unpauseServer(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -598,18 +598,18 @@ class Client(Iface): self._iprot.readMessageEnd() return - def togglePause(self, ): + def togglePause(self,): self.send_togglePause() return self.recv_togglePause() - def send_togglePause(self, ): + def send_togglePause(self,): self._oprot.writeMessageBegin('togglePause', TMessageType.CALL, self._seqid) args = togglePause_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_togglePause(self, ): + def recv_togglePause(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -623,18 +623,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "togglePause failed: unknown result"); - def statusServer(self, ): + def statusServer(self,): self.send_statusServer() return self.recv_statusServer() - def send_statusServer(self, ): + def send_statusServer(self,): self._oprot.writeMessageBegin('statusServer', TMessageType.CALL, self._seqid) args = statusServer_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_statusServer(self, ): + def recv_statusServer(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -648,18 +648,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "statusServer failed: unknown result"); - def freeSpace(self, ): + def freeSpace(self,): self.send_freeSpace() return self.recv_freeSpace() - def send_freeSpace(self, ): + def send_freeSpace(self,): self._oprot.writeMessageBegin('freeSpace', TMessageType.CALL, self._seqid) args = freeSpace_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_freeSpace(self, ): + def recv_freeSpace(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -673,18 +673,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "freeSpace failed: unknown result"); - def getServerVersion(self, ): + def getServerVersion(self,): self.send_getServerVersion() return self.recv_getServerVersion() - def send_getServerVersion(self, ): + def send_getServerVersion(self,): self._oprot.writeMessageBegin('getServerVersion', TMessageType.CALL, self._seqid) args = getServerVersion_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getServerVersion(self, ): + def recv_getServerVersion(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -698,18 +698,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getServerVersion failed: unknown result"); - def kill(self, ): + def kill(self,): self.send_kill() self.recv_kill() - def send_kill(self, ): + def send_kill(self,): self._oprot.writeMessageBegin('kill', TMessageType.CALL, self._seqid) args = kill_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_kill(self, ): + def recv_kill(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -721,18 +721,18 @@ class Client(Iface): self._iprot.readMessageEnd() return - def restart(self, ): + def restart(self,): self.send_restart() self.recv_restart() - def send_restart(self, ): + def send_restart(self,): self._oprot.writeMessageBegin('restart', TMessageType.CALL, self._seqid) args = restart_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_restart(self, ): + def recv_restart(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -760,7 +760,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getLog(self, ): + def recv_getLog(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -774,18 +774,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getLog failed: unknown result"); - def isTimeDownload(self, ): + def isTimeDownload(self,): self.send_isTimeDownload() return self.recv_isTimeDownload() - def send_isTimeDownload(self, ): + def send_isTimeDownload(self,): self._oprot.writeMessageBegin('isTimeDownload', TMessageType.CALL, self._seqid) args = isTimeDownload_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_isTimeDownload(self, ): + def recv_isTimeDownload(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -799,18 +799,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "isTimeDownload failed: unknown result"); - def isTimeReconnect(self, ): + def isTimeReconnect(self,): self.send_isTimeReconnect() return self.recv_isTimeReconnect() - def send_isTimeReconnect(self, ): + def send_isTimeReconnect(self,): self._oprot.writeMessageBegin('isTimeReconnect', TMessageType.CALL, self._seqid) args = isTimeReconnect_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_isTimeReconnect(self, ): + def recv_isTimeReconnect(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -824,18 +824,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "isTimeReconnect failed: unknown result"); - def toggleReconnect(self, ): + def toggleReconnect(self,): self.send_toggleReconnect() return self.recv_toggleReconnect() - def send_toggleReconnect(self, ): + def send_toggleReconnect(self,): self._oprot.writeMessageBegin('toggleReconnect', TMessageType.CALL, self._seqid) args = toggleReconnect_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_toggleReconnect(self, ): + def recv_toggleReconnect(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -865,7 +865,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_generatePackages(self, ): + def recv_generatePackages(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -895,7 +895,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_checkURLs(self, ): + def recv_checkURLs(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -927,7 +927,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_parseURLs(self, ): + def recv_parseURLs(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -957,7 +957,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_checkOnlineStatus(self, ): + def recv_checkOnlineStatus(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -991,7 +991,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_checkOnlineStatusContainer(self, ): + def recv_checkOnlineStatusContainer(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1021,7 +1021,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_pollResults(self, ): + def recv_pollResults(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1035,18 +1035,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "pollResults failed: unknown result"); - def statusDownloads(self, ): + def statusDownloads(self,): self.send_statusDownloads() return self.recv_statusDownloads() - def send_statusDownloads(self, ): + def send_statusDownloads(self,): self._oprot.writeMessageBegin('statusDownloads', TMessageType.CALL, self._seqid) args = statusDownloads_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_statusDownloads(self, ): + def recv_statusDownloads(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1076,7 +1076,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPackageData(self, ): + def recv_getPackageData(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1108,7 +1108,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPackageInfo(self, ): + def recv_getPackageInfo(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1140,7 +1140,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getFileData(self, ): + def recv_getFileData(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1156,18 +1156,18 @@ class Client(Iface): raise result.e raise TApplicationException(TApplicationException.MISSING_RESULT, "getFileData failed: unknown result"); - def getQueue(self, ): + def getQueue(self,): self.send_getQueue() return self.recv_getQueue() - def send_getQueue(self, ): + def send_getQueue(self,): self._oprot.writeMessageBegin('getQueue', TMessageType.CALL, self._seqid) args = getQueue_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getQueue(self, ): + def recv_getQueue(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1181,18 +1181,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getQueue failed: unknown result"); - def getCollector(self, ): + def getCollector(self,): self.send_getCollector() return self.recv_getCollector() - def send_getCollector(self, ): + def send_getCollector(self,): self._oprot.writeMessageBegin('getCollector', TMessageType.CALL, self._seqid) args = getCollector_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCollector(self, ): + def recv_getCollector(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1206,18 +1206,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getCollector failed: unknown result"); - def getQueueData(self, ): + def getQueueData(self,): self.send_getQueueData() return self.recv_getQueueData() - def send_getQueueData(self, ): + def send_getQueueData(self,): self._oprot.writeMessageBegin('getQueueData', TMessageType.CALL, self._seqid) args = getQueueData_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getQueueData(self, ): + def recv_getQueueData(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1231,18 +1231,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getQueueData failed: unknown result"); - def getCollectorData(self, ): + def getCollectorData(self,): self.send_getCollectorData() return self.recv_getCollectorData() - def send_getCollectorData(self, ): + def send_getCollectorData(self,): self._oprot.writeMessageBegin('getCollectorData', TMessageType.CALL, self._seqid) args = getCollectorData_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCollectorData(self, ): + def recv_getCollectorData(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1272,7 +1272,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPackageOrder(self, ): + def recv_getPackageOrder(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1302,7 +1302,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getFileOrder(self, ): + def recv_getFileOrder(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1334,7 +1334,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_generateAndAddPackages(self, ): + def recv_generateAndAddPackages(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1368,7 +1368,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_addPackage(self, ): + def recv_addPackage(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1400,7 +1400,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_addFiles(self, ): + def recv_addFiles(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1430,7 +1430,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_uploadContainer(self, ): + def recv_uploadContainer(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1458,7 +1458,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_deleteFiles(self, ): + def recv_deleteFiles(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1486,7 +1486,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_deletePackages(self, ): + def recv_deletePackages(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1514,7 +1514,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_pushToQueue(self, ): + def recv_pushToQueue(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1542,7 +1542,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_pullFromQueue(self, ): + def recv_pullFromQueue(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1570,7 +1570,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_restartPackage(self, ): + def recv_restartPackage(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1598,7 +1598,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_restartFile(self, ): + def recv_restartFile(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1626,7 +1626,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_recheckPackage(self, ): + def recv_recheckPackage(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1638,18 +1638,18 @@ class Client(Iface): self._iprot.readMessageEnd() return - def stopAllDownloads(self, ): + def stopAllDownloads(self,): self.send_stopAllDownloads() self.recv_stopAllDownloads() - def send_stopAllDownloads(self, ): + def send_stopAllDownloads(self,): self._oprot.writeMessageBegin('stopAllDownloads', TMessageType.CALL, self._seqid) args = stopAllDownloads_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_stopAllDownloads(self, ): + def recv_stopAllDownloads(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1677,7 +1677,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_stopDownloads(self, ): + def recv_stopDownloads(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1707,7 +1707,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_setPackageName(self, ): + def recv_setPackageName(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1737,7 +1737,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_movePackage(self, ): + def recv_movePackage(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1767,7 +1767,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_moveFiles(self, ): + def recv_moveFiles(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1797,7 +1797,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_orderPackage(self, ): + def recv_orderPackage(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1827,7 +1827,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_orderFile(self, ): + def recv_orderFile(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1857,7 +1857,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_setPackageData(self, ): + def recv_setPackageData(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1871,18 +1871,18 @@ class Client(Iface): raise result.e return - def deleteFinished(self, ): + def deleteFinished(self,): self.send_deleteFinished() return self.recv_deleteFinished() - def send_deleteFinished(self, ): + def send_deleteFinished(self,): self._oprot.writeMessageBegin('deleteFinished', TMessageType.CALL, self._seqid) args = deleteFinished_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_deleteFinished(self, ): + def recv_deleteFinished(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1896,18 +1896,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "deleteFinished failed: unknown result"); - def restartFailed(self, ): + def restartFailed(self,): self.send_restartFailed() self.recv_restartFailed() - def send_restartFailed(self, ): + def send_restartFailed(self,): self._oprot.writeMessageBegin('restartFailed', TMessageType.CALL, self._seqid) args = restartFailed_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_restartFailed(self, ): + def recv_restartFailed(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1935,7 +1935,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getEvents(self, ): + def recv_getEvents(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1965,7 +1965,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAccounts(self, ): + def recv_getAccounts(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -1979,18 +1979,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getAccounts failed: unknown result"); - def getAccountTypes(self, ): + def getAccountTypes(self,): self.send_getAccountTypes() return self.recv_getAccountTypes() - def send_getAccountTypes(self, ): + def send_getAccountTypes(self,): self._oprot.writeMessageBegin('getAccountTypes', TMessageType.CALL, self._seqid) args = getAccountTypes_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAccountTypes(self, ): + def recv_getAccountTypes(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2026,7 +2026,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_updateAccount(self, ): + def recv_updateAccount(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2056,7 +2056,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_removeAccount(self, ): + def recv_removeAccount(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2086,7 +2086,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_login(self, ): + def recv_login(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2118,7 +2118,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getUserData(self, ): + def recv_getUserData(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2132,18 +2132,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getUserData failed: unknown result"); - def getAllUserData(self, ): + def getAllUserData(self,): self.send_getAllUserData() return self.recv_getAllUserData() - def send_getAllUserData(self, ): + def send_getAllUserData(self,): self._oprot.writeMessageBegin('getAllUserData', TMessageType.CALL, self._seqid) args = getAllUserData_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAllUserData(self, ): + def recv_getAllUserData(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2157,18 +2157,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllUserData failed: unknown result"); - def getServices(self, ): + def getServices(self,): self.send_getServices() return self.recv_getServices() - def send_getServices(self, ): + def send_getServices(self,): self._oprot.writeMessageBegin('getServices', TMessageType.CALL, self._seqid) args = getServices_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getServices(self, ): + def recv_getServices(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2200,7 +2200,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_hasService(self, ): + def recv_hasService(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2230,7 +2230,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_call(self, ): + def recv_call(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2248,18 +2248,18 @@ class Client(Iface): raise result.e raise TApplicationException(TApplicationException.MISSING_RESULT, "call failed: unknown result"); - def getAllInfo(self, ): + def getAllInfo(self,): self.send_getAllInfo() return self.recv_getAllInfo() - def send_getAllInfo(self, ): + def send_getAllInfo(self,): self._oprot.writeMessageBegin('getAllInfo', TMessageType.CALL, self._seqid) args = getAllInfo_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAllInfo(self, ): + def recv_getAllInfo(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2289,7 +2289,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getInfoByPlugin(self, ): + def recv_getInfoByPlugin(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2303,18 +2303,18 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "getInfoByPlugin failed: unknown result"); - def isCaptchaWaiting(self, ): + def isCaptchaWaiting(self,): self.send_isCaptchaWaiting() return self.recv_isCaptchaWaiting() - def send_isCaptchaWaiting(self, ): + def send_isCaptchaWaiting(self,): self._oprot.writeMessageBegin('isCaptchaWaiting', TMessageType.CALL, self._seqid) args = isCaptchaWaiting_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_isCaptchaWaiting(self, ): + def recv_isCaptchaWaiting(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2344,7 +2344,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCaptchaTask(self, ): + def recv_getCaptchaTask(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2374,7 +2374,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCaptchaTaskStatus(self, ): + def recv_getCaptchaTaskStatus(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -2406,7 +2406,7 @@ class Client(Iface): self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_setCaptchaResult(self, ): + def recv_setCaptchaResult(self,): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() @@ -3315,9 +3315,9 @@ class getConfigValue_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'category', None, None, ), # 1 - (2, TType.STRING, 'option', None, None, ), # 2 - (3, TType.STRING, 'section', None, None, ), # 3 + (1, TType.STRING, 'category', None, None,), # 1 + (2, TType.STRING, 'option', None, None,), # 2 + (3, TType.STRING, 'section', None, None,), # 3 ) def __init__(self, category=None, option=None, section=None,): @@ -3337,7 +3337,7 @@ class getConfigValue_result(TBase): ] thrift_spec = ( - (0, TType.STRING, 'success', None, None, ), # 0 + (0, TType.STRING, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -3362,10 +3362,10 @@ class setConfigValue_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'category', None, None, ), # 1 - (2, TType.STRING, 'option', None, None, ), # 2 - (3, TType.STRING, 'value', None, None, ), # 3 - (4, TType.STRING, 'section', None, None, ), # 4 + (1, TType.STRING, 'category', None, None,), # 1 + (2, TType.STRING, 'option', None, None,), # 2 + (3, TType.STRING, 'value', None, None,), # 3 + (4, TType.STRING, 'section', None, None,), # 4 ) def __init__(self, category=None, option=None, value=None, section=None,): @@ -3404,7 +3404,7 @@ class getConfig_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.STRUCT,(ConfigSection, ConfigSection.thrift_spec)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.STRUCT, (ConfigSection, ConfigSection.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -3431,7 +3431,7 @@ class getPluginConfig_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.STRUCT,(ConfigSection, ConfigSection.thrift_spec)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.STRUCT, (ConfigSection, ConfigSection.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -3494,7 +3494,7 @@ class togglePause_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.BOOL, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -3521,7 +3521,7 @@ class statusServer_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (ServerStatus, ServerStatus.thrift_spec), None, ), # 0 + (0, TType.STRUCT, 'success', (ServerStatus, ServerStatus.thrift_spec), None,), # 0 ) def __init__(self, success=None,): @@ -3548,7 +3548,7 @@ class freeSpace_result(TBase): ] thrift_spec = ( - (0, TType.I64, 'success', None, None, ), # 0 + (0, TType.I64, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -3575,7 +3575,7 @@ class getServerVersion_result(TBase): ] thrift_spec = ( - (0, TType.STRING, 'success', None, None, ), # 0 + (0, TType.STRING, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -3630,7 +3630,7 @@ class getLog_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'offset', None, None, ), # 1 + (1, TType.I32, 'offset', None, None,), # 1 ) def __init__(self, offset=None,): @@ -3648,7 +3648,7 @@ class getLog_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRING,None), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRING, None), None,), # 0 ) def __init__(self, success=None,): @@ -3675,7 +3675,7 @@ class isTimeDownload_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.BOOL, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -3702,7 +3702,7 @@ class isTimeReconnect_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.BOOL, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -3729,7 +3729,7 @@ class toggleReconnect_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.BOOL, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -3748,7 +3748,7 @@ class generatePackages_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 + (1, TType.LIST, 'links', (TType.STRING, None), None,), # 1 ) def __init__(self, links=None,): @@ -3766,7 +3766,7 @@ class generatePackages_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.LIST, (TType.STRING, None)), None,), # 0 ) def __init__(self, success=None,): @@ -3785,7 +3785,7 @@ class checkURLs_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 + (1, TType.LIST, 'urls', (TType.STRING, None), None,), # 1 ) def __init__(self, urls=None,): @@ -3803,7 +3803,7 @@ class checkURLs_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.LIST, (TType.STRING, None)), None,), # 0 ) def __init__(self, success=None,): @@ -3824,8 +3824,8 @@ class parseURLs_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'html', None, None, ), # 1 - (2, TType.STRING, 'url', None, None, ), # 2 + (1, TType.STRING, 'html', None, None,), # 1 + (2, TType.STRING, 'url', None, None,), # 2 ) def __init__(self, html=None, url=None,): @@ -3844,7 +3844,7 @@ class parseURLs_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.LIST, (TType.STRING, None)), None,), # 0 ) def __init__(self, success=None,): @@ -3863,7 +3863,7 @@ class checkOnlineStatus_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 + (1, TType.LIST, 'urls', (TType.STRING, None), None,), # 1 ) def __init__(self, urls=None,): @@ -3881,7 +3881,7 @@ class checkOnlineStatus_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 + (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None,), # 0 ) def __init__(self, success=None,): @@ -3904,9 +3904,9 @@ class checkOnlineStatusContainer_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 - (2, TType.STRING, 'filename', None, None, ), # 2 - (3, TType.STRING, 'data', None, None, ), # 3 + (1, TType.LIST, 'urls', (TType.STRING, None), None,), # 1 + (2, TType.STRING, 'filename', None, None,), # 2 + (3, TType.STRING, 'data', None, None,), # 3 ) def __init__(self, urls=None, filename=None, data=None,): @@ -3926,7 +3926,7 @@ class checkOnlineStatusContainer_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 + (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None,), # 0 ) def __init__(self, success=None,): @@ -3945,7 +3945,7 @@ class pollResults_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'rid', None, None, ), # 1 + (1, TType.I32, 'rid', None, None,), # 1 ) def __init__(self, rid=None,): @@ -3963,7 +3963,7 @@ class pollResults_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 + (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None,), # 0 ) def __init__(self, success=None,): @@ -3990,7 +3990,7 @@ class statusDownloads_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(DownloadInfo, DownloadInfo.thrift_spec)), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT, (DownloadInfo, DownloadInfo.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -4009,7 +4009,7 @@ class getPackageData_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -4029,8 +4029,8 @@ class getPackageData_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (PackageData, PackageData.thrift_spec), None, ), # 0 - (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 + (0, TType.STRUCT, 'success', (PackageData, PackageData.thrift_spec), None,), # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None,), # 1 ) def __init__(self, success=None, e=None,): @@ -4050,7 +4050,7 @@ class getPackageInfo_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -4070,8 +4070,8 @@ class getPackageInfo_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (PackageData, PackageData.thrift_spec), None, ), # 0 - (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 + (0, TType.STRUCT, 'success', (PackageData, PackageData.thrift_spec), None,), # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None,), # 1 ) def __init__(self, success=None, e=None,): @@ -4091,7 +4091,7 @@ class getFileData_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 + (1, TType.I32, 'fid', None, None,), # 1 ) def __init__(self, fid=None,): @@ -4111,8 +4111,8 @@ class getFileData_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (FileData, FileData.thrift_spec), None, ), # 0 - (1, TType.STRUCT, 'e', (FileDoesNotExists, FileDoesNotExists.thrift_spec), None, ), # 1 + (0, TType.STRUCT, 'success', (FileData, FileData.thrift_spec), None,), # 0 + (1, TType.STRUCT, 'e', (FileDoesNotExists, FileDoesNotExists.thrift_spec), None,), # 1 ) def __init__(self, success=None, e=None,): @@ -4140,7 +4140,7 @@ class getQueue_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT, (PackageData, PackageData.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -4167,7 +4167,7 @@ class getCollector_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT, (PackageData, PackageData.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -4194,7 +4194,7 @@ class getQueueData_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT, (PackageData, PackageData.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -4221,7 +4221,7 @@ class getCollectorData_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT, (PackageData, PackageData.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -4240,7 +4240,7 @@ class getPackageOrder_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'destination', None, None, ), # 1 + (1, TType.I32, 'destination', None, None,), # 1 ) def __init__(self, destination=None,): @@ -4258,7 +4258,7 @@ class getPackageOrder_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.I16,None,TType.I32,None), None, ), # 0 + (0, TType.MAP, 'success', (TType.I16, None, TType.I32, None), None,), # 0 ) def __init__(self, success=None,): @@ -4277,7 +4277,7 @@ class getFileOrder_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -4295,7 +4295,7 @@ class getFileOrder_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.I16,None,TType.I32,None), None, ), # 0 + (0, TType.MAP, 'success', (TType.I16, None, TType.I32, None), None,), # 0 ) def __init__(self, success=None,): @@ -4316,8 +4316,8 @@ class generateAndAddPackages_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 - (2, TType.I32, 'dest', None, None, ), # 2 + (1, TType.LIST, 'links', (TType.STRING, None), None,), # 1 + (2, TType.I32, 'dest', None, None,), # 2 ) def __init__(self, links=None, dest=None,): @@ -4336,7 +4336,7 @@ class generateAndAddPackages_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.I32,None), None, ), # 0 + (0, TType.LIST, 'success', (TType.I32, None), None,), # 0 ) def __init__(self, success=None,): @@ -4359,9 +4359,9 @@ class addPackage_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 - (3, TType.I32, 'dest', None, None, ), # 3 + (1, TType.STRING, 'name', None, None,), # 1 + (2, TType.LIST, 'links', (TType.STRING, None), None,), # 2 + (3, TType.I32, 'dest', None, None,), # 3 ) def __init__(self, name=None, links=None, dest=None,): @@ -4381,7 +4381,7 @@ class addPackage_result(TBase): ] thrift_spec = ( - (0, TType.I32, 'success', None, None, ), # 0 + (0, TType.I32, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -4402,8 +4402,8 @@ class addFiles_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 + (1, TType.I32, 'pid', None, None,), # 1 + (2, TType.LIST, 'links', (TType.STRING, None), None,), # 2 ) def __init__(self, pid=None, links=None,): @@ -4434,8 +4434,8 @@ class uploadContainer_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'filename', None, None, ), # 1 - (2, TType.STRING, 'data', None, None, ), # 2 + (1, TType.STRING, 'filename', None, None,), # 1 + (2, TType.STRING, 'data', None, None,), # 2 ) def __init__(self, filename=None, data=None,): @@ -4464,7 +4464,7 @@ class deleteFiles_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 + (1, TType.LIST, 'fids', (TType.I32, None), None,), # 1 ) def __init__(self, fids=None,): @@ -4492,7 +4492,7 @@ class deletePackages_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'pids', (TType.I32,None), None, ), # 1 + (1, TType.LIST, 'pids', (TType.I32, None), None,), # 1 ) def __init__(self, pids=None,): @@ -4520,7 +4520,7 @@ class pushToQueue_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -4548,7 +4548,7 @@ class pullFromQueue_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -4576,7 +4576,7 @@ class restartPackage_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -4604,7 +4604,7 @@ class restartFile_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 + (1, TType.I32, 'fid', None, None,), # 1 ) def __init__(self, fid=None,): @@ -4632,7 +4632,7 @@ class recheckPackage_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -4678,7 +4678,7 @@ class stopDownloads_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 + (1, TType.LIST, 'fids', (TType.I32, None), None,), # 1 ) def __init__(self, fids=None,): @@ -4708,8 +4708,8 @@ class setPackageName_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.STRING, 'name', None, None, ), # 2 + (1, TType.I32, 'pid', None, None,), # 1 + (2, TType.STRING, 'name', None, None,), # 2 ) def __init__(self, pid=None, name=None,): @@ -4740,8 +4740,8 @@ class movePackage_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'destination', None, None, ), # 1 - (2, TType.I32, 'pid', None, None, ), # 2 + (1, TType.I32, 'destination', None, None,), # 1 + (2, TType.I32, 'pid', None, None,), # 2 ) def __init__(self, destination=None, pid=None,): @@ -4772,8 +4772,8 @@ class moveFiles_args(TBase): thrift_spec = ( None, # 0 - (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 - (2, TType.I32, 'pid', None, None, ), # 2 + (1, TType.LIST, 'fids', (TType.I32, None), None,), # 1 + (2, TType.I32, 'pid', None, None,), # 2 ) def __init__(self, fids=None, pid=None,): @@ -4804,8 +4804,8 @@ class orderPackage_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.I16, 'position', None, None, ), # 2 + (1, TType.I32, 'pid', None, None,), # 1 + (2, TType.I16, 'position', None, None,), # 2 ) def __init__(self, pid=None, position=None,): @@ -4836,8 +4836,8 @@ class orderFile_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 - (2, TType.I16, 'position', None, None, ), # 2 + (1, TType.I32, 'fid', None, None,), # 1 + (2, TType.I16, 'position', None, None,), # 2 ) def __init__(self, fid=None, position=None,): @@ -4868,8 +4868,8 @@ class setPackageData_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.MAP, 'data', (TType.STRING,None,TType.STRING,None), None, ), # 2 + (1, TType.I32, 'pid', None, None,), # 1 + (2, TType.MAP, 'data', (TType.STRING, None, TType.STRING, None), None,), # 2 ) def __init__(self, pid=None, data=None,): @@ -4889,7 +4889,7 @@ class setPackageData_result(TBase): thrift_spec = ( None, # 0 - (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None,), # 1 ) def __init__(self, e=None,): @@ -4916,7 +4916,7 @@ class deleteFinished_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.I32,None), None, ), # 0 + (0, TType.LIST, 'success', (TType.I32, None), None,), # 0 ) def __init__(self, success=None,): @@ -4953,7 +4953,7 @@ class getEvents_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'uuid', None, None, ), # 1 + (1, TType.STRING, 'uuid', None, None,), # 1 ) def __init__(self, uuid=None,): @@ -4971,7 +4971,7 @@ class getEvents_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(EventInfo, EventInfo.thrift_spec)), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT, (EventInfo, EventInfo.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -4990,7 +4990,7 @@ class getAccounts_args(TBase): thrift_spec = ( None, # 0 - (1, TType.BOOL, 'refresh', None, None, ), # 1 + (1, TType.BOOL, 'refresh', None, None,), # 1 ) def __init__(self, refresh=None,): @@ -5008,7 +5008,7 @@ class getAccounts_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(AccountInfo, AccountInfo.thrift_spec)), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT, (AccountInfo, AccountInfo.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -5035,7 +5035,7 @@ class getAccountTypes_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRING,None), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRING, None), None,), # 0 ) def __init__(self, success=None,): @@ -5060,10 +5060,10 @@ class updateAccount_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'plugin', None, None, ), # 1 - (2, TType.STRING, 'account', None, None, ), # 2 - (3, TType.STRING, 'password', None, None, ), # 3 - (4, TType.MAP, 'options', (TType.STRING,None,TType.STRING,None), None, ), # 4 + (1, TType.STRING, 'plugin', None, None,), # 1 + (2, TType.STRING, 'account', None, None,), # 2 + (3, TType.STRING, 'password', None, None,), # 3 + (4, TType.MAP, 'options', (TType.STRING, None, TType.STRING, None), None,), # 4 ) def __init__(self, plugin=None, account=None, password=None, options=None,): @@ -5096,8 +5096,8 @@ class removeAccount_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'plugin', None, None, ), # 1 - (2, TType.STRING, 'account', None, None, ), # 2 + (1, TType.STRING, 'plugin', None, None,), # 1 + (2, TType.STRING, 'account', None, None,), # 2 ) def __init__(self, plugin=None, account=None,): @@ -5128,8 +5128,8 @@ class login_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'username', None, None, ), # 1 - (2, TType.STRING, 'password', None, None, ), # 2 + (1, TType.STRING, 'username', None, None,), # 1 + (2, TType.STRING, 'password', None, None,), # 2 ) def __init__(self, username=None, password=None,): @@ -5148,7 +5148,7 @@ class login_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.BOOL, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -5169,8 +5169,8 @@ class getUserData_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'username', None, None, ), # 1 - (2, TType.STRING, 'password', None, None, ), # 2 + (1, TType.STRING, 'username', None, None,), # 1 + (2, TType.STRING, 'password', None, None,), # 2 ) def __init__(self, username=None, password=None,): @@ -5189,7 +5189,7 @@ class getUserData_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (UserData, UserData.thrift_spec), None, ), # 0 + (0, TType.STRUCT, 'success', (UserData, UserData.thrift_spec), None,), # 0 ) def __init__(self, success=None,): @@ -5216,7 +5216,7 @@ class getAllUserData_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.STRUCT,(UserData, UserData.thrift_spec)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.STRUCT, (UserData, UserData.thrift_spec)), None,), # 0 ) def __init__(self, success=None,): @@ -5243,7 +5243,7 @@ class getServices_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.MAP,(TType.STRING,None,TType.STRING,None)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.MAP, (TType.STRING, None, TType.STRING, None)), None,), # 0 ) def __init__(self, success=None,): @@ -5264,8 +5264,8 @@ class hasService_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'plugin', None, None, ), # 1 - (2, TType.STRING, 'func', None, None, ), # 2 + (1, TType.STRING, 'plugin', None, None,), # 1 + (2, TType.STRING, 'func', None, None,), # 2 ) def __init__(self, plugin=None, func=None,): @@ -5284,7 +5284,7 @@ class hasService_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.BOOL, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -5303,7 +5303,7 @@ class call_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRUCT, 'info', (ServiceCall, ServiceCall.thrift_spec), None, ), # 1 + (1, TType.STRUCT, 'info', (ServiceCall, ServiceCall.thrift_spec), None,), # 1 ) def __init__(self, info=None,): @@ -5325,9 +5325,9 @@ class call_result(TBase): ] thrift_spec = ( - (0, TType.STRING, 'success', None, None, ), # 0 - (1, TType.STRUCT, 'ex', (ServiceDoesNotExists, ServiceDoesNotExists.thrift_spec), None, ), # 1 - (2, TType.STRUCT, 'e', (ServiceException, ServiceException.thrift_spec), None, ), # 2 + (0, TType.STRING, 'success', None, None,), # 0 + (1, TType.STRUCT, 'ex', (ServiceDoesNotExists, ServiceDoesNotExists.thrift_spec), None,), # 1 + (2, TType.STRUCT, 'e', (ServiceException, ServiceException.thrift_spec), None,), # 2 ) def __init__(self, success=None, ex=None, e=None,): @@ -5356,7 +5356,7 @@ class getAllInfo_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.MAP,(TType.STRING,None,TType.STRING,None)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.MAP, (TType.STRING, None, TType.STRING, None)), None,), # 0 ) def __init__(self, success=None,): @@ -5375,7 +5375,7 @@ class getInfoByPlugin_args(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'plugin', None, None, ), # 1 + (1, TType.STRING, 'plugin', None, None,), # 1 ) def __init__(self, plugin=None,): @@ -5393,7 +5393,7 @@ class getInfoByPlugin_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.STRING,None), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING, None, TType.STRING, None), None,), # 0 ) def __init__(self, success=None,): @@ -5420,7 +5420,7 @@ class isCaptchaWaiting_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.BOOL, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -5439,7 +5439,7 @@ class getCaptchaTask_args(TBase): thrift_spec = ( None, # 0 - (1, TType.BOOL, 'exclusive', None, None, ), # 1 + (1, TType.BOOL, 'exclusive', None, None,), # 1 ) def __init__(self, exclusive=None,): @@ -5457,7 +5457,7 @@ class getCaptchaTask_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (CaptchaTask, CaptchaTask.thrift_spec), None, ), # 0 + (0, TType.STRUCT, 'success', (CaptchaTask, CaptchaTask.thrift_spec), None,), # 0 ) def __init__(self, success=None,): @@ -5476,7 +5476,7 @@ class getCaptchaTaskStatus_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'tid', None, None, ), # 1 + (1, TType.I32, 'tid', None, None,), # 1 ) def __init__(self, tid=None,): @@ -5494,7 +5494,7 @@ class getCaptchaTaskStatus_result(TBase): ] thrift_spec = ( - (0, TType.STRING, 'success', None, None, ), # 0 + (0, TType.STRING, 'success', None, None,), # 0 ) def __init__(self, success=None,): @@ -5515,8 +5515,8 @@ class setCaptchaResult_args(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'tid', None, None, ), # 1 - (2, TType.STRING, 'result', None, None, ), # 2 + (1, TType.I32, 'tid', None, None,), # 1 + (2, TType.STRING, 'result', None, None,), # 2 ) def __init__(self, tid=None, result=None,): @@ -5531,4 +5531,3 @@ class setCaptchaResult_result(TBase): thrift_spec = ( ) - diff --git a/module/remote/thriftbackend/thriftgen/pyload/__init__.py b/module/remote/thriftbackend/thriftgen/pyload/__init__.py index ce7f52598..9a0fb88bf 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/__init__.py +++ b/module/remote/thriftbackend/thriftgen/pyload/__init__.py @@ -1 +1,3 @@ +# -*- coding: utf-8 -*- + __all__ = ['ttypes', 'constants', 'Pyload'] diff --git a/module/remote/thriftbackend/thriftgen/pyload/constants.py b/module/remote/thriftbackend/thriftgen/pyload/constants.py index f8960dc63..3bdd64cc1 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/constants.py +++ b/module/remote/thriftbackend/thriftgen/pyload/constants.py @@ -3,9 +3,8 @@ # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # -# options string: py:slots,dynamic +# options string: py:slots, dynamic # from thrift.Thrift import TType, TMessageType, TException from ttypes import * - diff --git a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py index 1299b515d..c2c50924e 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py +++ b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py @@ -3,7 +3,7 @@ # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # -# options string: py:slots,dynamic +# options string: py:slots, dynamic # from thrift.Thrift import TType, TMessageType, TException @@ -190,22 +190,22 @@ class DownloadInfo(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 - (2, TType.STRING, 'name', None, None, ), # 2 - (3, TType.I64, 'speed', None, None, ), # 3 - (4, TType.I32, 'eta', None, None, ), # 4 - (5, TType.STRING, 'format_eta', None, None, ), # 5 - (6, TType.I64, 'bleft', None, None, ), # 6 - (7, TType.I64, 'size', None, None, ), # 7 - (8, TType.STRING, 'format_size', None, None, ), # 8 - (9, TType.BYTE, 'percent', None, None, ), # 9 - (10, TType.I32, 'status', None, None, ), # 10 - (11, TType.STRING, 'statusmsg', None, None, ), # 11 - (12, TType.STRING, 'format_wait', None, None, ), # 12 - (13, TType.I64, 'wait_until', None, None, ), # 13 - (14, TType.I32, 'packageID', None, None, ), # 14 - (15, TType.STRING, 'packageName', None, None, ), # 15 - (16, TType.STRING, 'plugin', None, None, ), # 16 + (1, TType.I32, 'fid', None, None,), # 1 + (2, TType.STRING, 'name', None, None,), # 2 + (3, TType.I64, 'speed', None, None,), # 3 + (4, TType.I32, 'eta', None, None,), # 4 + (5, TType.STRING, 'format_eta', None, None,), # 5 + (6, TType.I64, 'bleft', None, None,), # 6 + (7, TType.I64, 'size', None, None,), # 7 + (8, TType.STRING, 'format_size', None, None,), # 8 + (9, TType.BYTE, 'percent', None, None,), # 9 + (10, TType.I32, 'status', None, None,), # 10 + (11, TType.STRING, 'statusmsg', None, None,), # 11 + (12, TType.STRING, 'format_wait', None, None,), # 12 + (13, TType.I64, 'wait_until', None, None,), # 13 + (14, TType.I32, 'packageID', None, None,), # 14 + (15, TType.STRING, 'packageName', None, None,), # 15 + (16, TType.STRING, 'plugin', None, None,), # 16 ) def __init__(self, fid=None, name=None, speed=None, eta=None, format_eta=None, bleft=None, size=None, format_size=None, percent=None, status=None, statusmsg=None, format_wait=None, wait_until=None, packageID=None, packageName=None, plugin=None,): @@ -251,13 +251,13 @@ class ServerStatus(TBase): thrift_spec = ( None, # 0 - (1, TType.BOOL, 'pause', None, None, ), # 1 - (2, TType.I16, 'active', None, None, ), # 2 - (3, TType.I16, 'queue', None, None, ), # 3 - (4, TType.I16, 'total', None, None, ), # 4 - (5, TType.I64, 'speed', None, None, ), # 5 - (6, TType.BOOL, 'download', None, None, ), # 6 - (7, TType.BOOL, 'reconnect', None, None, ), # 7 + (1, TType.BOOL, 'pause', None, None,), # 1 + (2, TType.I16, 'active', None, None,), # 2 + (3, TType.I16, 'queue', None, None,), # 3 + (4, TType.I16, 'total', None, None,), # 4 + (5, TType.I64, 'speed', None, None,), # 5 + (6, TType.BOOL, 'download', None, None,), # 6 + (7, TType.BOOL, 'reconnect', None, None,), # 7 ) def __init__(self, pause=None, active=None, queue=None, total=None, speed=None, download=None, reconnect=None,): @@ -288,10 +288,10 @@ class ConfigItem(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.STRING, 'description', None, None, ), # 2 - (3, TType.STRING, 'value', None, None, ), # 3 - (4, TType.STRING, 'type', None, None, ), # 4 + (1, TType.STRING, 'name', None, None,), # 1 + (2, TType.STRING, 'description', None, None,), # 2 + (3, TType.STRING, 'value', None, None,), # 3 + (4, TType.STRING, 'type', None, None,), # 4 ) def __init__(self, name=None, description=None, value=None, type=None,): @@ -319,10 +319,10 @@ class ConfigSection(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.STRING, 'description', None, None, ), # 2 - (3, TType.LIST, 'items', (TType.STRUCT,(ConfigItem, ConfigItem.thrift_spec)), None, ), # 3 - (4, TType.STRING, 'outline', None, None, ), # 4 + (1, TType.STRING, 'name', None, None,), # 1 + (2, TType.STRING, 'description', None, None,), # 2 + (3, TType.LIST, 'items', (TType.STRUCT, (ConfigItem, ConfigItem.thrift_spec)), None,), # 3 + (4, TType.STRING, 'outline', None, None,), # 4 ) def __init__(self, name=None, description=None, items=None, outline=None,): @@ -364,17 +364,17 @@ class FileData(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 - (2, TType.STRING, 'url', None, None, ), # 2 - (3, TType.STRING, 'name', None, None, ), # 3 - (4, TType.STRING, 'plugin', None, None, ), # 4 - (5, TType.I64, 'size', None, None, ), # 5 - (6, TType.STRING, 'format_size', None, None, ), # 6 - (7, TType.I32, 'status', None, None, ), # 7 - (8, TType.STRING, 'statusmsg', None, None, ), # 8 - (9, TType.I32, 'packageID', None, None, ), # 9 - (10, TType.STRING, 'error', None, None, ), # 10 - (11, TType.I16, 'order', None, None, ), # 11 + (1, TType.I32, 'fid', None, None,), # 1 + (2, TType.STRING, 'url', None, None,), # 2 + (3, TType.STRING, 'name', None, None,), # 3 + (4, TType.STRING, 'plugin', None, None,), # 4 + (5, TType.I64, 'size', None, None,), # 5 + (6, TType.STRING, 'format_size', None, None,), # 6 + (7, TType.I32, 'status', None, None,), # 7 + (8, TType.STRING, 'statusmsg', None, None,), # 8 + (9, TType.I32, 'packageID', None, None,), # 9 + (10, TType.STRING, 'error', None, None,), # 10 + (11, TType.I16, 'order', None, None,), # 11 ) def __init__(self, fid=None, url=None, name=None, plugin=None, size=None, format_size=None, status=None, statusmsg=None, packageID=None, error=None, order=None,): @@ -427,19 +427,19 @@ class PackageData(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.STRING, 'name', None, None, ), # 2 - (3, TType.STRING, 'folder', None, None, ), # 3 - (4, TType.STRING, 'site', None, None, ), # 4 - (5, TType.STRING, 'password', None, None, ), # 5 - (6, TType.I32, 'dest', None, None, ), # 6 - (7, TType.I16, 'order', None, None, ), # 7 - (8, TType.I16, 'linksdone', None, None, ), # 8 - (9, TType.I64, 'sizedone', None, None, ), # 9 - (10, TType.I64, 'sizetotal', None, None, ), # 10 - (11, TType.I16, 'linkstotal', None, None, ), # 11 - (12, TType.LIST, 'links', (TType.STRUCT,(FileData, FileData.thrift_spec)), None, ), # 12 - (13, TType.LIST, 'fids', (TType.I32,None), None, ), # 13 + (1, TType.I32, 'pid', None, None,), # 1 + (2, TType.STRING, 'name', None, None,), # 2 + (3, TType.STRING, 'folder', None, None,), # 3 + (4, TType.STRING, 'site', None, None,), # 4 + (5, TType.STRING, 'password', None, None,), # 5 + (6, TType.I32, 'dest', None, None,), # 6 + (7, TType.I16, 'order', None, None,), # 7 + (8, TType.I16, 'linksdone', None, None,), # 8 + (9, TType.I64, 'sizedone', None, None,), # 9 + (10, TType.I64, 'sizetotal', None, None,), # 10 + (11, TType.I16, 'linkstotal', None, None,), # 11 + (12, TType.LIST, 'links', (TType.STRUCT, (FileData, FileData.thrift_spec)), None,), # 12 + (13, TType.LIST, 'fids', (TType.I32, None), None,), # 13 ) def __init__(self, pid=None, name=None, folder=None, site=None, password=None, dest=None, order=None, linksdone=None, sizedone=None, sizetotal=None, linkstotal=None, links=None, fids=None,): @@ -486,15 +486,15 @@ class InteractionTask(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'iid', None, None, ), # 1 - (2, TType.I32, 'input', None, None, ), # 2 - (3, TType.LIST, 'structure', (TType.STRING,None), None, ), # 3 - (4, TType.LIST, 'preset', (TType.STRING,None), None, ), # 4 - (5, TType.I32, 'output', None, None, ), # 5 - (6, TType.LIST, 'data', (TType.STRING,None), None, ), # 6 - (7, TType.STRING, 'title', None, None, ), # 7 - (8, TType.STRING, 'description', None, None, ), # 8 - (9, TType.STRING, 'plugin', None, None, ), # 9 + (1, TType.I32, 'iid', None, None,), # 1 + (2, TType.I32, 'input', None, None,), # 2 + (3, TType.LIST, 'structure', (TType.STRING, None), None,), # 3 + (4, TType.LIST, 'preset', (TType.STRING, None), None,), # 4 + (5, TType.I32, 'output', None, None,), # 5 + (6, TType.LIST, 'data', (TType.STRING, None), None,), # 6 + (7, TType.STRING, 'title', None, None,), # 7 + (8, TType.STRING, 'description', None, None,), # 8 + (9, TType.STRING, 'plugin', None, None,), # 9 ) def __init__(self, iid=None, input=None, structure=None, preset=None, output=None, data=None, title=None, description=None, plugin=None,): @@ -527,10 +527,10 @@ class CaptchaTask(TBase): thrift_spec = ( None, # 0 - (1, TType.I16, 'tid', None, None, ), # 1 - (2, TType.STRING, 'data', None, None, ), # 2 - (3, TType.STRING, 'type', None, None, ), # 3 - (4, TType.STRING, 'resultType', None, None, ), # 4 + (1, TType.I16, 'tid', None, None,), # 1 + (2, TType.STRING, 'data', None, None,), # 2 + (3, TType.STRING, 'type', None, None,), # 3 + (4, TType.STRING, 'resultType', None, None,), # 4 ) def __init__(self, tid=None, data=None, type=None, resultType=None,): @@ -558,10 +558,10 @@ class EventInfo(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'eventname', None, None, ), # 1 - (2, TType.I32, 'id', None, None, ), # 2 - (3, TType.I32, 'type', None, None, ), # 3 - (4, TType.I32, 'destination', None, None, ), # 4 + (1, TType.STRING, 'eventname', None, None,), # 1 + (2, TType.I32, 'id', None, None,), # 2 + (3, TType.I32, 'type', None, None,), # 3 + (4, TType.I32, 'destination', None, None,), # 4 ) def __init__(self, eventname=None, id=None, type=None, destination=None,): @@ -591,11 +591,11 @@ class UserData(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.STRING, 'email', None, None, ), # 2 - (3, TType.I32, 'role', None, None, ), # 3 - (4, TType.I32, 'permission', None, None, ), # 4 - (5, TType.STRING, 'templateName', None, None, ), # 5 + (1, TType.STRING, 'name', None, None,), # 1 + (2, TType.STRING, 'email', None, None,), # 2 + (3, TType.I32, 'role', None, None,), # 3 + (4, TType.I32, 'permission', None, None,), # 4 + (5, TType.STRING, 'templateName', None, None,), # 5 ) def __init__(self, name=None, email=None, role=None, permission=None, templateName=None,): @@ -632,14 +632,14 @@ class AccountInfo(TBase): thrift_spec = ( None, # 0 - (1, TType.I64, 'validuntil', None, None, ), # 1 - (2, TType.STRING, 'login', None, None, ), # 2 - (3, TType.MAP, 'options', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 3 - (4, TType.BOOL, 'valid', None, None, ), # 4 - (5, TType.I64, 'trafficleft', None, None, ), # 5 - (6, TType.I64, 'maxtraffic', None, None, ), # 6 - (7, TType.BOOL, 'premium', None, None, ), # 7 - (8, TType.STRING, 'type', None, None, ), # 8 + (1, TType.I64, 'validuntil', None, None,), # 1 + (2, TType.STRING, 'login', None, None,), # 2 + (3, TType.MAP, 'options', (TType.STRING, None, TType.LIST, (TType.STRING, None)), None,), # 3 + (4, TType.BOOL, 'valid', None, None,), # 4 + (5, TType.I64, 'trafficleft', None, None,), # 5 + (6, TType.I64, 'maxtraffic', None, None,), # 6 + (7, TType.BOOL, 'premium', None, None,), # 7 + (8, TType.STRING, 'type', None, None,), # 8 ) def __init__(self, validuntil=None, login=None, options=None, valid=None, trafficleft=None, maxtraffic=None, premium=None, type=None,): @@ -671,10 +671,10 @@ class ServiceCall(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'plugin', None, None, ), # 1 - (2, TType.STRING, 'func', None, None, ), # 2 - (3, TType.LIST, 'arguments', (TType.STRING,None), None, ), # 3 - (4, TType.BOOL, 'parseArguments', None, None, ), # 4 + (1, TType.STRING, 'plugin', None, None,), # 1 + (2, TType.STRING, 'func', None, None,), # 2 + (3, TType.LIST, 'arguments', (TType.STRING, None), None,), # 3 + (4, TType.BOOL, 'parseArguments', None, None,), # 4 ) def __init__(self, plugin=None, func=None, arguments=None, parseArguments=None,): @@ -704,11 +704,11 @@ class OnlineStatus(TBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.STRING, 'plugin', None, None, ), # 2 - (3, TType.STRING, 'packagename', None, None, ), # 3 - (4, TType.I32, 'status', None, None, ), # 4 - (5, TType.I64, 'size', None, None, ), # 5 + (1, TType.STRING, 'name', None, None,), # 1 + (2, TType.STRING, 'plugin', None, None,), # 2 + (3, TType.STRING, 'packagename', None, None,), # 3 + (4, TType.I32, 'status', None, None,), # 4 + (5, TType.I64, 'size', None, None,), # 5 ) def __init__(self, name=None, plugin=None, packagename=None, status=None, size=None,): @@ -733,8 +733,8 @@ class OnlineCheck(TBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'rid', None, None, ), # 1 - (2, TType.MAP, 'data', (TType.STRING,None,TType.STRUCT,(OnlineStatus, OnlineStatus.thrift_spec)), None, ), # 2 + (1, TType.I32, 'rid', None, None,), # 1 + (2, TType.MAP, 'data', (TType.STRING, None, TType.STRUCT, (OnlineStatus, OnlineStatus.thrift_spec)), None,), # 2 ) def __init__(self, rid=None, data=None,): @@ -754,7 +754,7 @@ class PackageDoesNotExists(TExceptionBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None,), # 1 ) def __init__(self, pid=None,): @@ -776,7 +776,7 @@ class FileDoesNotExists(TExceptionBase): thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 + (1, TType.I32, 'fid', None, None,), # 1 ) def __init__(self, fid=None,): @@ -800,8 +800,8 @@ class ServiceDoesNotExists(TExceptionBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'plugin', None, None, ), # 1 - (2, TType.STRING, 'func', None, None, ), # 2 + (1, TType.STRING, 'plugin', None, None,), # 1 + (2, TType.STRING, 'func', None, None,), # 2 ) def __init__(self, plugin=None, func=None,): @@ -824,7 +824,7 @@ class ServiceException(TExceptionBase): thrift_spec = ( None, # 0 - (1, TType.STRING, 'msg', None, None, ), # 1 + (1, TType.STRING, 'msg', None, None,), # 1 ) def __init__(self, msg=None,): @@ -832,4 +832,3 @@ class ServiceException(TExceptionBase): def __str__(self): return repr(self) - diff --git a/module/setup.py b/module/setup.py index 42b24859f..d0aee4b28 100644 --- a/module/setup.py +++ b/module/setup.py @@ -1,48 +1,30 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: RaNaN -""" -from getpass import getpass -import module.common.pylgettext as gettext + import os -from os import makedirs -from os.path import abspath -from os.path import dirname -from os.path import exists -from os.path import join -from subprocess import PIPE -from subprocess import call import sys -from sys import exit -from module.utils import get_console_encoding -class Setup(): - """ - pyLoads initial setup configuration assistent - """ +import module.common.pylgettext as gettext + +from getpass import getpass +from os import makedirs +from os.path import abspath, dirname, exists, join +from subprocess import PIPE, call + +from module.utils import get_console_encoding, versiontuple + + +class Setup: + """ pyLoads initial setup configuration assistant """ def __init__(self, path, config): self.path = path self.config = config self.stdin_encoding = get_console_encoding(sys.stdin.encoding) + def start(self): langs = self.config.getMetaData("general", "language")["type"].split(";") - lang = self.ask(u"Choose your Language / WÀhle deine Sprache", "en", langs) + lang = self.ask(u"Choose setup language", "en", langs) gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) translation = gettext.translation("setup", join(self.path, "locale"), languages=[lang, "en"], fallback=True) translation.install(True) @@ -52,143 +34,172 @@ class Setup(): #Input shorthand for no self.no = _("n") - # print "" + # print # print _("Would you like to configure pyLoad via Webinterface?") # print _("You need a Browser and a connection to this PC for it.") # viaweb = self.ask(_("Start initial webinterface for configuration?"), "y", bool=True) # if viaweb: # try: - # from module.web import ServerThread + # from module.threads import ServerThread # ServerThread.setup = self - # from module.web import webinterface + # import module.webui as webinterface # webinterface.run_simple() # return False # except Exception, e: # print "Setup failed with this error: ", e # print "Falling back to commandline setup." - - print "" - print _("Welcome to the pyLoad Configuration Assistent.") + print + print + print _("Welcome to the pyLoad Configuration Assistant.") print _("It will check your system and make a basic setup in order to run pyLoad.") - print "" + print print _("The value in brackets [] always is the default value,") print _("in case you don't want to change it or you are unsure what to choose, just hit enter.") print _( - "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyLoadCore.") - print _("If you have any problems with this assistent hit STRG-C,") - print _("to abort and don't let him start with pyLoadCore automatically anymore.") - print "" - print _("When you are ready for system check, hit enter.") - raw_input() + "Don't forget: You can always rerun this assistant with --setup or -s parameter, when you start pyload.py .") + print _("If you have any problems with this assistant hit STRG-C,") + print _("to abort and don't let him start with pyload.py automatically anymore.") + print + print + raw_input(_("When you are ready for system check, hit enter.")) + print + print - basic, ssl, captcha, gui, web, js = self.system_check() - print "" + basic, ssl, captcha, web, js = self.system_check() + print + print if not basic: print _("You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad.") print _("Please correct this and re-run pyLoad.") + print print _("Setup will now close.") - raw_input() + print + print + raw_input(_("Press Enter to exit.")) return False raw_input(_("System check finished, hit enter to see your status report.")) - print "" + print + print print _("## Status ##") - print "" + print avail = [] - if self.check_module("Crypto"): avail.append(_("container decrypting")) - if ssl: avail.append(_("ssl connection")) - if captcha: avail.append(_("automatic captcha decryption")) - if gui: avail.append(_("GUI")) - if web: avail.append(_("Webinterface")) - if js: avail.append(_("extended Click'N'Load")) + if self.check_module("Crypto"): + avail.append(_("container decrypting")) + if ssl: + avail.append(_("ssl connection")) + if captcha: + avail.append(_("automatic captcha decryption")) + if web: + avail.append(_("webinterface")) + if js: + avail.append(_("extended Click'N'Load")) string = "" for av in avail: string += ", " + av - print _("Features available:") + string[1:] - print "" + print _("AVAILABLE FEATURES:") + string[1:] + print if len(avail) < 5: - print _("Featues missing: ") - print + print _("MISSING FEATURES: ") if not self.check_module("Crypto"): - print _("no py-crypto available") + print _("- no py-crypto available") print _("You need this if you want to decrypt container files.") - print "" + print if not ssl: - print _("no SSL available") + print _("- no SSL available") print _("This is needed if you want to establish a secure connection to core or webinterface.") print _("If you only want to access locally to pyLoad ssl is not usefull.") - print "" + print if not captcha: - print _("no Captcha Recognition available") + print _("- no Captcha Recognition available") print _("Only needed for some hosters and as freeuser.") - print "" - - if not gui: - print _("Gui not available") - print _("The Graphical User Interface.") - print "" + print if not js: - print _("no JavaScript engine found") + print _("- no JavaScript engine found") print _("You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino") + print + print print _("You can abort the setup now and fix some dependicies if you want.") + print con = self.ask(_("Continue with setup?"), self.yes, bool=True) if not con: return False - print "" - print _("Do you want to change the config path? Current is %s") % abspath("") - print _( - "If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it.") - path = self.ask(_("Change config path?"), self.no, bool=True) + print + print + print _("CURRENT CONFIG PATH: %s") % abspath("") + print + print _("NOTE: If you use pyLoad on a server or the home partition lives on an iternal flash it may be a good idea to change it.") + path = self.ask(_("Do you want to change the config path?"), self.no, bool=True) if path: + print self.conf_path() #calls exit when changed - print "" + print print _("Do you want to configure login data and basic settings?") print _("This is recommend for first run.") con = self.ask(_("Make basic setup?"), self.yes, bool=True) if con: + print + print self.conf_basic() if ssl: - print "" + print print _("Do you want to configure ssl?") ssl = self.ask(_("Configure ssl?"), self.no, bool=True) if ssl: + print + print self.conf_ssl() if web: - print "" + print print _("Do you want to configure webinterface?") web = self.ask(_("Configure webinterface?"), self.yes, bool=True) if web: + print + print self.conf_web() - print "" - print _("Setup finished successfully.") - print _("Hit enter to exit and restart pyLoad") - raw_input() + print + print + print _("Setup finished successfully!") + print + print + raw_input(_("Hit enter to exit and restart pyLoad.")) return True + def system_check(self): """ make a systemcheck and return the results""" + + print _("## System Information ##") + print + print _("Platform: %s") % sys.platform + print _("Operating System: %s") % os.name + print _("Python: %s") % sys.version.replace("\n", "") + print + print + print _("## System Check ##") + print if sys.version_info[:2] > (2, 7): print _("Your python version is to new, Please use Python 2.6/2.7") @@ -208,7 +219,7 @@ class Setup(): basic = python and curl and sqlite - print "" + print crypto = self.check_module("Crypto") self.print_dep("pycrypto", crypto) @@ -216,10 +227,10 @@ class Setup(): ssl = self.check_module("OpenSSL") self.print_dep("py-OpenSSL", ssl) - print "" + print - pil = self.check_module("Image") - self.print_dep("py-imaging", pil) + pil = self.check_module("PIL.Image") + self.print_dep("PIL/Pillow", pil) if os.name == "nt": tesser = self.check_prog([join(pypath, "tesseract", "tesseract.exe"), "-v"]) @@ -230,71 +241,74 @@ class Setup(): captcha = pil and tesser - print "" - - gui = self.check_module("PyQt4") - self.print_dep("PyQt4", gui) - - print "" - jinja = True + print try: import jinja2 v = jinja2.__version__ - if v and "unknown" not in v: - if not v.startswith("2.5") and not v.startswith("2.6"): - print _("Your installed jinja2 version %s seems too old.") % jinja2.__version__ - print _("You can safely continue but if the webinterface is not working,") - print _("please upgrade or deinstall it, pyLoad includes a sufficient jinja2 libary.") - print - jinja = False + if v and versiontuple(v) < (2, 5, 0): + jinja = False + else: + jinja = True except: - pass + jinja = False + + jinja = self.print_dep("jinja2", jinja) - self.print_dep("jinja2", jinja) beaker = self.check_module("beaker") self.print_dep("beaker", beaker) + bjoern = self.check_module("bjoern") + self.print_dep("bjoern", bjoern) + web = sqlite and beaker from module.common import JsEngine - js = True if JsEngine.ENGINE else False self.print_dep(_("JS engine"), js) - return basic, ssl, captcha, gui, web, js + if not jinja: + print + print + print _("WARNING: Your installed jinja2 version %s seems too old.") % jinja2.__version__ + print _("You can safely continue but if the webinterface is not working,") + print _("please upgrade or uninstall it, because pyLoad self-includes jinja2 libary.") + + return basic, ssl, captcha, web, js + def conf_basic(self): - print "" print _("## Basic Setup ##") - print "" - print _("The following logindata is valid for CLI, GUI and webinterface.") - + print + print _("The following logindata is valid for CLI and webinterface.") + from module.database import DatabaseBackend db = DatabaseBackend(None) db.setup() + print _("NOTE: Consider a password of 10 or more symbols if you expect to access from outside your local network (ex. internet).") + print username = self.ask(_("Username"), "User") password = self.ask("", "", password=True) db.addUser(username, password) db.shutdown() - print "" + print print _("External clients (GUI, CLI or other) need remote access to work over the network.") print _("However, if you only want to use the webinterface you may disable it to save ram.") - self.config["remote"]["activated"] = self.ask(_("Enable remote access"), self.yes, bool=True) + self.config["remote"]["activated"] = self.ask(_("Enable remote access"), self.no, bool=True) - print "" + print langs = self.config.getMetaData("general", "language") - self.config["general"]["language"] = self.ask(_("Language"), "en", langs["type"].split(";")) + self.config["general"]["language"] = self.ask(_("Choose pyLoad language"), "en", langs["type"].split(";")) - self.config["general"]["download_folder"] = self.ask(_("Downloadfolder"), "Downloads") + print + self.config["general"]["download_folder"] = self.ask(_("Download folder"), "Downloads") + print self.config["download"]["max_downloads"] = self.ask(_("Max parallel downloads"), "3") - #print _("You should disable checksum proofing, if you have low hardware requirements.") - #self.config["general"]["checksum"] = self.ask(_("Proof checksum?"), "y", bool=True) - + print reconnect = self.ask(_("Use Reconnect?"), self.no, bool=True) self.config["reconnect"]["activated"] = reconnect if reconnect: @@ -302,47 +316,51 @@ class Setup(): def conf_web(self): - print "" print _("## Webinterface Setup ##") - print "" + print self.config["webinterface"]["activated"] = self.ask(_("Activate webinterface?"), self.yes, bool=True) - print "" + print print _("Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally.") self.config["webinterface"]["host"] = self.ask(_("Address"), "0.0.0.0") self.config["webinterface"]["port"] = self.ask(_("Port"), "8000") - print "" + print print _("pyLoad offers several server backends, now following a short explanation.") - print "builtin:", _("Default server, best choice if you dont know which one to choose.") - print "threaded:", _("This server offers SSL and is a good alternative to builtin.") - print "fastcgi:", _( - "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job.") - print "lightweight:", _("Very fast alternative written in C, requires libev and linux knowlegde.") - print "\t", _("Get it from here: https://github.com/jonashaag/bjoern, compile it") - print "\t", _("and copy bjoern.so to module/lib") + print "- builtin:", _("Default server; best choice if you plan to use pyLoad just for you.") + print "- threaded:", _("Support SSL connection and can serve simultaneously more client flawlessly.") + print "- fastcgi:", _( + "Can be used by apache, lighttpd, etc.; needs to be properly configured before.") + if os.name != "nt": + print "- lightweight:", _("Very fast alternative to builtin; requires libev and bjoern packages.") print - print _( - "Attention: In some rare cases the builtin server is not working, if you notice problems with the webinterface") + print _("NOTE: In some rare cases the builtin server is not working, if you notice problems with the webinterface") print _("come back here and change the builtin server to the threaded one here.") - self.config["webinterface"]["server"] = self.ask(_("Server"), "builtin", - ["builtin", "threaded", "fastcgi", "lightweight"]) + if os.name == "nt": + servers = ["builtin", "threaded", "fastcgi"] + default = "threaded" + else: + servers = ["builtin", "threaded", "fastcgi", "lightweight"] + default = "lightweight" if self.check_module("bjoern") else "builtin" + + self.config["webinterface"]["server"] = self.ask(_("Server"), default, servers) + def conf_ssl(self): - print "" print _("## SSL Setup ##") - print "" + print print _("Execute these commands from pyLoad config folder to make ssl certificates:") - print "" + print print "openssl genrsa -out ssl.key 1024" print "openssl req -new -key ssl.key -out ssl.csr" print "openssl req -days 36500 -x509 -key ssl.key -in ssl.csr > ssl.crt " - print "" + print print _("If you're done and everything went fine, you can activate ssl now.") self.config["ssl"]["activated"] = self.ask(_("Activate SSL?"), self.yes, bool=True) + def set_user(self): gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) translation = gettext.translation("setup", join(self.path, "locale"), @@ -366,13 +384,13 @@ class Setup(): if not action in ("1", "2", "3", "4"): continue elif action == "1": - print "" + print username = self.ask(_("Username"), "User") password = self.ask("", "", password=True) db.addUser(username, password) noaction = False elif action == "2": - print "" + print print _("Users") print "-----" users = db.listUsers() @@ -380,9 +398,9 @@ class Setup(): for user in users: print user print "-----" - print "" + print elif action == "3": - print "" + print username = self.ask(_("Username"), "") if username: db.removeUser(username) @@ -393,6 +411,7 @@ class Setup(): if not noaction: db.shutdown() + def conf_path(self, trans=False): if trans: gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) @@ -400,8 +419,8 @@ class Setup(): languages=[self.config["general"]["language"], "en"], fallback=True) translation.install(True) - print _("Setting new configpath, current configuration will not be transfered!") - path = self.ask(_("Configpath"), abspath("")) + print _("Setting new config path, current configuration will not be transfered!") + path = self.ask(_("CONFIG PATH"), abspath("")) try: path = join(pypath, path) if not exists(path): @@ -409,19 +428,23 @@ class Setup(): f = open(join(pypath, "module", "config", "configdir"), "wb") f.write(path) f.close() - print _("Configpath changed, setup will now close, please restart to go on.") - print _("Press Enter to exit.") - raw_input() - exit() + print + print + print _("pyLoad config path changed, setup will now close!") + print + print + raw_input(_("Press Enter to exit.")) + sys.exit() except Exception, e: print _("Setting config path failed: %s") % str(e) + def print_dep(self, name, value): """Print Status of dependency""" if value: print _("%s: OK") % name else: - print _("%s: missing") % name + print _("%s: MISSING") % name def check_module(self, module): @@ -431,6 +454,7 @@ class Setup(): except: return False + def check_prog(self, command): pipe = PIPE try: @@ -439,6 +463,7 @@ class Setup(): except: return False + def ask(self, qst, default, answers=[], bool=False, password=False): """produce one line to asking for input""" if answers: @@ -459,13 +484,17 @@ class Setup(): if password: p1 = True p2 = False + pwlen = 8 while p1 != p2: # getpass(_("Password: ")) will crash on systems with broken locales (Win, NAS) sys.stdout.write(_("Password: ")) p1 = getpass("") - if len(p1) < 4: - print _("Password too short. Use at least 4 symbols.") + if len(p1) < pwlen: + print _("Password too short! Use at least %s symbols." % pwlen) + continue + elif not p1.isalnum(): + print _("Password must be alphanumeric.") continue sys.stdout.write(_("Password (again): ")) @@ -475,13 +504,13 @@ class Setup(): return p1 else: print _("Passwords did not match.") - + while True: try: input = raw_input(qst + " %s: " % info) except KeyboardInterrupt: print "\nSetup interrupted" - exit() + sys.exit() input = input.decode(self.stdin_encoding) @@ -489,10 +518,10 @@ class Setup(): input = default if bool: - # yes, true,t are inputs for booleans with value true + # yes, true, t are inputs for booleans with value true if input.lower().strip() in [self.yes, _("yes"), _("true"), _("t"), "yes"]: return True - # no, false,f are inputs for booleans with value false + # no, false, f are inputs for booleans with value false elif input.lower().strip() in [self.no, _("no"), _("false"), _("f"), "no"]: return False else: @@ -507,8 +536,3 @@ class Setup(): return input else: print _("Invalid Input") - - -if __name__ == "__main__": - test = Setup(join(abspath(dirname(__file__)), ".."), None) - test.start() diff --git a/module/PluginThread.py b/module/threads/PluginThread.py index 56c36c778..03e0bb31b 100644 --- a/module/PluginThread.py +++ b/module/threads/PluginThread.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ @@ -31,16 +30,16 @@ from types import MethodType from pycurl import error -from PyFile import PyFile -from plugins.Plugin import Abort, Fail, Reconnect, Retry, SkipDownload -from common.packagetools import parseNames -from utils import save_join -from Api import OnlineStatus +from module.PyFile import PyFile +from module.plugins.Plugin import Abort, Fail, Reconnect, Retry, SkipDownload +from module.common.packagetools import parseNames +from module.utils import safe_join +from module.Api import OnlineStatus class PluginThread(Thread): """abstract base class for thread types""" - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def __init__(self, manager): """Constructor""" Thread.__init__(self) @@ -64,11 +63,11 @@ class PluginThread(Thread): for f in listdir(join("tmp", pyfile.pluginname)): try: # avoid encoding errors - zip.write(join("tmp", pyfile.pluginname, f), save_join(pyfile.pluginname, f)) + zip.write(join("tmp", pyfile.pluginname, f), safe_join(pyfile.pluginname, f)) except: pass - info = zipfile.ZipInfo(save_join(pyfile.pluginname, "debug_Report.txt"), gmtime()) + info = zipfile.ZipInfo(safe_join(pyfile.pluginname, "debug_Report.txt"), gmtime()) info.external_attr = 0644 << 16L # change permissions zip.writestr(info, dump) @@ -150,7 +149,7 @@ class PluginThread(Thread): class DownloadThread(PluginThread): """thread for downloading files from 'real' hoster plugins""" - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def __init__(self, manager): """Constructor""" PluginThread.__init__(self, manager) @@ -160,7 +159,7 @@ class DownloadThread(PluginThread): self.start() - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def run(self): """run method""" pyfile = None @@ -317,7 +316,6 @@ class DownloadThread(PluginThread): pyfile.checkIfProcessed() exc_clear() - #pyfile.plugin.req.clean() self.active = False @@ -423,7 +421,7 @@ class DecrypterThread(PluginThread): class HookThread(PluginThread): """thread for hooks""" - #---------------------------------------------------------------------- + #-------------------------------------------------------------------------- def __init__(self, m, function, args, kwargs): """Constructor""" PluginThread.__init__(self, m) @@ -461,7 +459,7 @@ class HookThread(PluginThread): #dirty method to filter out exceptions if "unexpected keyword argument 'thread'" not in e.args[0]: raise - + del self.kwargs["thread"] self.f(*self.args, **self.kwargs) finally: diff --git a/module/web/ServerThread.py b/module/threads/ServerThread.py index 84667e5f6..e9fe14708 100644 --- a/module/web/ServerThread.py +++ b/module/threads/ServerThread.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python from __future__ import with_statement from os.path import exists @@ -27,48 +26,48 @@ class WebServer(threading.Thread): self.setDaemon(True) def run(self): - import webinterface + import module.webui as webinterface global webinterface - if self.https: - if not exists(self.cert) or not exists(self.key): - log.warning(_("SSL certificates not found.")) - self.https = False + reset = False + + if self.https and (not exists(self.cert) or not exists(self.key)): + log.warning(_("SSL certificates not found.")) + self.https = False if self.server in ("lighttpd", "nginx"): log.warning(_("Sorry, we dropped support for starting %s directly within pyLoad") % self.server) log.warning(_("You can use the threaded server which offers good performance and ssl,")) log.warning(_("of course you can still use your existing %s with pyLoads fastcgi server") % self.server) log.warning(_("sample configs are located in the module/web/servers directory")) - self.server = "builtin" - - if self.server == "fastcgi": + reset = True + elif self.server == "fastcgi": try: import flup except: log.warning(_("Can't use %(server)s, python-flup is not installed!") % { "server": self.server}) - self.server = "builtin" - elif self.server == "lightweight": - try: - import bjoern - except Exception, e: - log.error(_("Error importing lightweight server: %s") % e) - log.warning(_("You need to download and compile bjoern, https://github.com/jonashaag/bjoern")) - log.warning(_("Copy the boern.so to module/lib folder or use setup.py install")) - log.warning(_("Of course you need to be familiar with linux and know how to compile software")) - self.server = "builtin" - - if os.name == "nt": - self.core.log.info(_("Server set to threaded, due to known performance problems on windows.")) - self.core.config['webinterface']['server'] = "threaded" - self.server = "threaded" - - - if self.server == "fastcgi": - self.start_fcgi() - elif self.server == "threaded": + reset = True + + if reset or self.server == "lightweight": + if os.name != "nt": + try: + import bjoern + except Exception, e: + log.error(_("Error importing lightweight server: %s") % e) + log.warning(_("You need to download and compile bjoern, https://github.com/jonashaag/bjoern")) + log.warning(_("Copy the boern.so to module/lib folder or use setup.py install")) + log.warning(_("Of course you need to be familiar with linux and know how to compile software")) + self.server = "builtin" + else: + self.core.log.info(_("Server set to threaded, due to known performance problems on windows.")) + self.core.config['webinterface']['server'] = "threaded" + self.server = "threaded" + + if self.server == "threaded": self.start_threaded() + elif self.server == "fastcgi": + self.start_fcgi() elif self.server == "lightweight": self.start_lightweight() else: diff --git a/module/threads/__init__.py b/module/threads/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/module/threads/__init__.py diff --git a/module/unescape.py b/module/unescape.py index d8999e077..74e7b5c67 100644 --- a/module/unescape.py +++ b/module/unescape.py @@ -1,3 +1,3 @@ from module.utils import html_unescape #deprecated -unescape = html_unescape
\ No newline at end of file +unescape = html_unescape diff --git a/module/utils.py b/module/utils.py index 8748b7693..5e8c2b12b 100644 --- a/module/utils.py +++ b/module/utils.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -""" Store all usefull functions here """ +""" Store all useful functions here """ import os import sys @@ -10,6 +10,7 @@ from os.path import join from string import maketrans from htmlentitydefs import name2codepoint + def chmod(*args): try: os.chmod(*args) @@ -27,24 +28,39 @@ def decode(string): def remove_chars(string, repl): """ removes all chars in repl from string""" - if type(string) == str: - return string.translate(maketrans("", ""), repl) - elif type(string) == unicode: - return string.translate(dict([(ord(s), None) for s in repl])) + if type(repl) == unicode: + for badc in list(repl): + string = string.replace(badc, "") + return string + else: + if type(string) == str: + return string.translate(maketrans("", ""), repl) + elif type(string) == unicode: + return string.translate(dict([(ord(s), None) for s in repl])) -def save_path(name): - #remove some chars +def safe_path(name): + """ remove bad chars """ + name = name.encode('ascii', 'replace') # Non-ASCII chars usually breaks file saving. Replacing. if os.name == 'nt': - return remove_chars(name, '/\\?%*:|"<>') + return remove_chars(name, u'\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32' + u'\33\34\35\36\37/\\?%*:|"<>') else: - return remove_chars(name, '/\\"') + return remove_chars(name, u'\0/\\"') + +#: Deprecated method +def save_path(name): + return safe_path(name) -def save_join(*args): +def safe_join(*args): """ joins a path, encoding aware """ return fs_encode(join(*[x if type(x) == unicode else decode(x) for x in args])) +#: Deprecated method +def save_join(*args): + return safe_join(*args) + # File System Encoding functions: # Use fs_encode before accesing files on disk, it will encode the string properly @@ -61,6 +77,7 @@ if sys.getfilesystemencoding().startswith('ANSI'): else: fs_encode = fs_decode = lambda x: x # do nothing + def get_console_encoding(enc): if os.name == "nt": if enc == "cp65001": # aka UTF-8 @@ -68,9 +85,10 @@ def get_console_encoding(enc): enc = "cp850" else: enc = "utf8" - + return enc + def compare_time(start, end): start = map(int, start) end = map(int, end) @@ -88,7 +106,7 @@ def formatSize(size): """formats size of bytes""" size = int(size) steps = 0 - sizes = ["B", "KiB", "MiB", "GiB", "TiB"] + sizes = ("B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB") while size > 1000: size /= 1024.0 steps += 1 @@ -107,32 +125,35 @@ def freeSpace(folder): ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(folder), None, None, ctypes.pointer(free_bytes)) return free_bytes.value else: - from os import statvfs - - s = statvfs(folder) + s = os.statvfs(folder) return s.f_bsize * s.f_bavail -def uniqify(seq, idfun=None): -# order preserving - if idfun is None: - def idfun(x): return x - seen = {} - result = [] - for item in seq: - marker = idfun(item) - # in old Python versions: - # if seen.has_key(marker) - # but in new ones: - if marker in seen: continue - seen[marker] = 1 - result.append(item) - return result +def fs_bsize(path): + """ get optimal file system buffer size (in bytes) for I/O calls """ + path = fs_encode(path) + + if os.name == "nt": + import ctypes + + drive = "%s\\" % os.path.splitdrive(path)[0] + cluster_sectors, sector_size = ctypes.c_longlong(0) + ctypes.windll.kernel32.GetDiskFreeSpaceW(ctypes.c_wchar_p(drive), ctypes.pointer(cluster_sectors), ctypes.pointer(sector_size), None, None) + return cluster_sectors * sector_size + else: + return os.statvfs(path).f_bsize + + +def uniqify(seq): #: Originally by Dave Kirby + """ removes duplicates from list, preserve order """ + seen = set() + seen_add = seen.add + return [x for x in seq if x not in seen and not seen_add(x)] def parseFileSize(string, unit=None): #returns bytes if not unit: - m = re.match(r"(\d*[\.,]?\d+)(.*)", string.strip().lower()) + m = re.match(r"([\d.,]+) *([a-zA-Z]*)", string.strip().lower()) if m: traffic = float(m.group(1).replace(",", ".")) unit = m.group(2) @@ -147,11 +168,17 @@ def parseFileSize(string, unit=None): #returns bytes #ignore case unit = unit.lower().strip() - if unit in ("gb", "gig", "gbyte", "gigabyte", "gib", "g"): + if unit in ("eb", "ebyte", "exabyte", "eib", "e"): + traffic *= 1 << 60 + elif unit in ("pb", "pbyte", "petabyte", "pib", "p"): + traffic *= 1 << 50 + elif unit in ("tb", "tbyte", "terabyte", "tib", "t"): + traffic *= 1 << 40 + elif unit in ("gb", "gbyte", "gigabyte", "gib", "g", "gig"): traffic *= 1 << 30 elif unit in ("mb", "mbyte", "megabyte", "mib", "m"): traffic *= 1 << 20 - elif unit in ("kb", "kib", "kilobyte", "kbyte", "k"): + elif unit in ("kb", "kbyte", "kilobyte", "kib", "k"): traffic *= 1 << 10 return traffic @@ -159,7 +186,7 @@ def parseFileSize(string, unit=None): #returns bytes def lock(func): def new(*args): - #print "Handler: %s args: %s" % (func,args[1:]) + #print "Handler: %s args: %s" % (func, args[1:]) args[0].lock.acquire() try: return func(*args) @@ -195,7 +222,6 @@ def html_unescape(text): """Removes HTML or XML character references and entities from a text string""" return re.sub("&#?\w+;", fixup, text) -if __name__ == "__main__": - print freeSpace(".") - print remove_chars("ab'cdgdsf''ds'", "'ghd") +def versiontuple(v): #: By kindall (http://stackoverflow.com/a/11887825) + return tuple(map(int, (v.split(".")))) diff --git a/module/web/media/default/css/default.css b/module/web/media/default/css/default.css deleted file mode 100644 index 116f9725a..000000000 --- a/module/web/media/default/css/default.css +++ /dev/null @@ -1,908 +0,0 @@ -.hidden { - display:none; -} -.leftalign { - text-align:left; -} -.centeralign { - text-align:center; -} -.rightalign { - text-align:right; -} - - -.dokuwiki div.plugin_translation ul li a.wikilink1:link, .dokuwiki div.plugin_translation ul li a.wikilink1:hover, .dokuwiki div.plugin_translation ul li a.wikilink1:active, .dokuwiki div.plugin_translation ul li a.wikilink1:visited { - background-color:#000080; - color:#fff !important; - text-decoration:none; - padding:0 0.2em; - margin:0.1em 0.2em; - border:none !important; -} -.dokuwiki div.plugin_translation ul li a.wikilink2:link, .dokuwiki div.plugin_translation ul li a.wikilink2:hover, .dokuwiki div.plugin_translation ul li a.wikilink2:active, .dokuwiki div.plugin_translation ul li a.wikilink2:visited { - background-color:#808080; - color:#fff !important; - text-decoration:none; - padding:0 0.2em; - margin:0.1em 0.2em; - border:none !important; -} - -.dokuwiki div.plugin_translation ul li a:hover img { - opacity:1.0; - height:15px; -} - -body { - margin:0; - padding:0; - background-color:white; - color:black; - font-size:12px; - font-family:Verdana, Helvetica, "Lucida Grande", Lucida, Arial, sans-serif; - font-family:sans-serif; - font-size:99, 96%; - font-size-adjust:none; - font-style:normal; - font-variant:normal; - font-weight:normal; - line-height:normal; -} -hr { - border-width:0; - border-bottom:1px #aaa dotted; -} -img { - border:none; -} -form { - margin:0px; - padding:0px; - border:none; - display:inline; - background:transparent; -} -ul li { - margin:5px; -} -textarea { - font-family:monospace; -} -table { - margin:0.5em 0; - border-collapse:collapse; -} -td { - padding:0.25em; - border:1pt solid #ADB9CC; -} -a { - color:#3465a4; - text-decoration:none; -} -a:hover { - text-decoration:underline; -} - -option { - border:0 none #fff; -} -strong.highlight { - background-color:#fc9; - padding:1pt; -} -#pagebottom { - clear:both; -} -hr { - height:1px; - color:#c0c0c0; - background-color:#c0c0c0; - border:none; - margin:.2em 0 .2em 0; -} - -.invisible { - margin:0px; - border:0px; - padding:0px; - height:0px; - visibility:hidden; -} -.left { - float:left !important; -} -.right { - float:right !important; -} -.center { - text-align:center; -} -div#body-wrapper { - padding:40px 40px 10px 40px; - font-size:127%; -} -div#content { - margin-top:-20px; - padding:0; - font-size:14px; - color:black; - line-height:1.5em; -} -h1, h2, h3, h4, h5, h6 { - background:transparent none repeat scroll 0 0; - border-bottom:1px solid #aaa; - color:black; - font-weight:normal; - margin:0; - padding:0; - padding-bottom:0.17em; - padding-top:0.5em; -} -h1 { - font-size:188%; - line-height:1.2em; - margin-bottom:0.1em; - padding-bottom:0; -} -h2 { - font-size:150%; -} -h3, h4, h5, h6 { - border-bottom:none; - font-weight:bold; -} -h3 { - font-size:132%; -} -h4 { - font-size:116%; -} -h5 { - font-size:100%; -} -h6 { - font-size:80%; -} -ul#page-actions, ul#page-actions-more { - float:right; - margin:10px 10px 0 10px; - padding:6px; - color:black; - background-color:#ececec; - list-style-type:none; - white-space: nowrap; - border-radius:5px; - -moz-border-radius:5px; -} -ul#user-actions { - padding:5px; - margin:0; - display:inline; - color:black; - background-color:#ececec; - list-style-type:none; - -moz-border-radius:3px; - border-radius:3px; -} -ul#page-actions li, ul#user-actions li, ul#page-actions-more li { - display:inline; -} -ul#page-actions a, ul#user-actions a, ul#page-actions-more a { - text-decoration:none; - color:black; - display:inline; - margin:0 3px; - padding:2px 0px 2px 18px; -} -ul#page-actions a:hover, ul#page-actions a:focus, ul#user-actions a:hover, ul#user-actions a:focus { - /*text-decoration:underline;*/ -} -/***************************/ -ul#page-actions2 { - float:left; - margin:10px 10px 0 10px; - padding:6px; - color:black; - background-color:#ececec; - list-style-type:none; - border-radius:5px; - -moz-border-radius:5px; -} -ul#user-actions2 { - padding:5px; - margin:0; - display:inline; - color:black; - background-color:#ececec; - list-style-type:none; - border-radius:3px; - -moz-border-radius:3px; -} -ul#page-actions2 li, ul#user-actions2 li { - display:inline; -} -ul#page-actions2 a, ul#user-actions2 a { - text-decoration:none; - color:black; - display:inline; - margin:0 3px; - padding:2px 0px 2px 18px; -} -ul#page-actions2 a:hover, ul#page-actions2 a:focus, ul#user-actions2 a:hover, ul#user-actions2 a:focus, -ul#page-actions-more a:hover, ul#page-actions-more a:focus{ - color: #4e7bb4; -} -/****************************/ -.hidden { - display:none; -} - -a.action.index { - background:transparent url(/media/default/img/wiki-tools-index.png) 0px 1px no-repeat; -} -a.action.recent { - background:transparent url(/media/default/img/wiki-tools-recent.png) 0px 1px no-repeat; -} -a.logout { - background:transparent url(/media/default/img/user-actions-logout.png) 0px 1px no-repeat; -} - -a.info { - background:transparent url(/media/default/img/user-info.png) 0px 1px no-repeat; -} - -a.admin { - background:transparent url(/media/default/img/user-actions-admin.png) 0px 1px no-repeat; -} -a.profile { - background:transparent url(/media/default/img/user-actions-profile.png) 0px 1px no-repeat; -} -a.create, a.edit { - background:transparent url(/media/default/img/page-tools-edit.png) 0px 1px no-repeat; -} -a.source, a.show { - background:transparent url(/media/default/img/page-tools-source.png) 0px 1px no-repeat; -} -a.revisions { - background:transparent url(/media/default/img/page-tools-revisions.png) 0px 1px no-repeat; -} -a.subscribe, a.unsubscribe { - background:transparent url(/media/default/img/page-tools-subscribe.png) 0px 1px no-repeat; -} -a.backlink { - background:transparent url(/media/default/img/page-tools-backlinks.png) 0px 1px no-repeat; -} -a.play { - background:transparent url(/media/default/img/control_play.png) 0px 1px no-repeat; -} -.time { - background:transparent url(/media/default/img/status_None.png) 0px 1px no-repeat; - padding: 2px 0px 2px 18px; - margin: 0px 3px; -} -.reconnect { - background:transparent url(/media/default/img/reconnect.png) 0px 1px no-repeat; - padding: 2px 0px 2px 18px; - margin: 0px 3px; -} -a.play:hover { - background:transparent url(/media/default/img/control_play_blue.png) 0px 1px no-repeat; -} -a.cancel { - background:transparent url(/media/default/img/control_cancel.png) 0px 1px no-repeat; -} -a.cancel:hover { - background:transparent url(/media/default/img/control_cancel_blue.png) 0px 1px no-repeat; -} -a.pause { - background:transparent url(/media/default/img/control_pause.png) 0px 1px no-repeat; -} -a.pause:hover { - background:transparent url(/media/default/img/control_pause_blue.png) 0px 1px no-repeat; - font-weight: bold; -} -a.stop { - background:transparent url(/media/default/img/control_stop.png) 0px 1px no-repeat; -} -a.stop:hover { - background:transparent url(/media/default/img/control_stop_blue.png) 0px 1px no-repeat; -} -a.add { - background:transparent url(/media/default/img/control_add.png) 0px 1px no-repeat; -} -a.add:hover { - background:transparent url(/media/default/img/control_add_blue.png) 0px 1px no-repeat; -} -a.cog { - background:transparent url(/media/default/img/cog.png) 0px 1px no-repeat; -} -#head-panel { - background:#525252 url(/media/default/img/head_bg1.png) bottom left repeat-x; -} -#head-panel h1 { - display:none; - margin:0; - text-decoration:none; - padding-top:0.8em; - padding-left:3.3em; - font-size:2.6em; - color:#eeeeec; -} -#head-panel #head-logo { - float:left; - margin:5px 0 -15px 5px; - padding:0; - overflow:visible; -} -#head-menu { - background:transparent url(/media/default/img/tabs-border-bottom.png) 0 100% repeat-x; - width:100%; - float:left; - margin:0; - padding:0; - padding-top:0.8em; -} -#head-menu ul { - list-style:none; - margin:0 1em 0 2em; -} -#head-menu ul li { - float:left; - margin:0; - margin-left:0.3em; - font-size:14px; - margin-bottom:4px; -} -#head-menu ul li.selected, #head-menu ul li:hover { - margin-bottom:0px; -} -#head-menu ul li a img { - height:22px; - width:22px; - vertical-align:middle; -} -#head-menu ul li a, #head-menu ul li a:link { - float:left; - text-decoration:none; - color:#555; - background:#eaeaea url(/media/default/img/tab-background.png) 0 100% repeat-x; - padding:3px 7px 3px 7px; - border:2px solid #ccc; - border-bottom:0px solid transparent; - padding-bottom:3px; - -moz-border-radius:5px; - border-radius:5px; -} -#head-menu ul li a:hover, #head-menu ul li a:focus { - color:#111; - padding-bottom:7px; - border-bottom:0px none transparent; - outline:none; - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; - -moz-border-radius-bottomright:0px; - -moz-border-radius-bottomleft:0px; -} -#head-menu ul li a:focus { - margin-bottom:-4px; -} -#head-menu ul li.selected a { - color:#3566A5; - background:#fff; - padding-bottom:7px; - border-bottom:0px none transparent; - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; - -moz-border-radius-bottomright:0px; - -moz-border-radius-bottomleft:0px; -} -#head-menu ul li.selected a:hover, #head-menu ul li.selected a:focus { - color:#111; -} -div#head-search-and-login { - float:right; - margin:0 1em 0 0; - background-color:#222; - padding:7px 7px 5px 5px; - color:white; - white-space: nowrap; - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-bottomright:6px; - -moz-border-radius-bottomleft:6px; -} -div#head-search-and-login form { - display:inline; - padding:0 3px; -} -div#head-search-and-login form input { - border:2px solid #888; - background:#eee; - font-size:14px; - padding:2px; - border-radius:3px; - -moz-border-radius:3px; -} -div#head-search-and-login form input:focus { - background:#fff; -} -#head-search { - font-size:14px; -} -#head-username, #head-password { - width:80px; - font-size:14px; -} -#pageinfo { - clear:both; - color:#888; - padding:0.6em 0; - margin:0; -} -#foot { - font-style:normal; - color:#888; - text-align:center; -} -#foot a { - color:#aaf; -} -#foot img { - vertical-align:middle; -} -div.toc { - border:1px dotted #888; - background:#f0f0f0; - margin:1em 0 1em 1em; - float:right; - font-size:95%; -} -div.toc .tocheader { - font-weight:bold; - margin:0.5em 1em; -} -div.toc ol { - margin:1em 0.5em 1em 1em; - padding:0; -} -div.toc ol li { - margin:0; - padding:0; - margin-left:1em; -} -div.toc ol ol { - margin:0.5em 0.5em 0.5em 1em; - padding:0; -} -div.recentchanges table { - clear:both; -} -div#editor-help { - font-size:90%; - border:1px dotted #888; - padding:0ex 1ex 1ex 1ex; - background:#f7f6f2; -} -div#preview { - margin-top:1em; -} -label.block { - display:block; - text-align:right; - font-weight:bold; -} -label.simple { - display:block; - text-align:left; - font-weight:normal; -} -label.block input.edit { - width:50%; -} -/*fieldset { - width:300px; - text-align:center; - padding:0.5em; - margin:auto; -} -*/ -div.editor { - margin:0 0 0 0; -} -table { - margin:0.5em 0; - border-collapse:collapse; -} -td { - padding:0.25em; - border:1pt solid #ADB9CC; -} -td p { - margin:0; - padding:0; -} -.u { - text-decoration:underline; -} -.footnotes ul { - padding:0 2em; - margin:0 0 1em; -} -.footnotes li { - list-style:none; -} -.userpref table, .userpref td { - border:none; -} -#message { - clear:both; - padding:5px 10px; - background-color:#eee; - border-bottom:2px solid #ccc; -} -#message p { - margin:5px 0; - padding:0; - font-weight:bold; -} -#message div.buttons { - font-weight:normal; -} -.diff { - width:99%; -} -.diff-title { - background-color:#C0C0C0; -} -.searchresult dd span { - font-weight:bold; -} -.boxtext { - font-family:tahoma, arial, sans-serif; - font-size:11px; - color:#000; - float:none; - padding:3px 0 0 10px; -} -.statusbutton { - width:32px; - height:32px; - float:left; - margin-left:-32px; - margin-right:5px; - opacity:0; - cursor:pointer -} -.dlsize { - float:left; - padding-right: 8px; -} -.dlspeed { - float:left; - padding-right: 8px; -} -.package { - margin-bottom: 10px; -} -.packagename { - font-weight: bold; -} - -.child { - margin-left: 20px; -} -.child_status { - margin-right: 10px; -} -.child_secrow { - font-size: 10px; -} - -.header, .header th { - text-align: left; - font-weight: normal; - background-color:#ececec; - -moz-border-radius:5px; - border-radius:5px; -} -.progress_bar { - background: #0C0; - height: 5px; - -} - -.queue { - border: none -} - -.queue tr td { - border: none -} - -.header, .header th{ - text-align: left; - font-weight: normal; -} - - -.clearer -{ - clear: both; - height: 1px; -} - -.left -{ - float: left; -} - -.right -{ - float: right; -} - - -.setfield -{ - display: table-cell; -} - -ul.tabs li a -{ - padding: 5px 16px 4px 15px; - border: none; - font-weight: bold; - - border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - -} - - -#tabs span -{ - display: none; -} - -#tabs span.selected -{ - display: inline; -} - -#tabsback -{ - background-color: #525252; - margin: 2px 0 0; - padding: 6px 4px 1px 4px; - - border-top-right-radius: 30px; - border-top-left-radius: 3px; - -moz-border-radius-topright: 30px; - -moz-border-radius-topleft: 3px; -} -ul.tabs -{ - list-style-type: none; - margin:0; - padding: 0 40px 0 0; -} - -ul.tabs li -{ - display: inline; - margin-left: 8px; -} - - -ul.tabs li a -{ - color: #42454a; - background-color: #eaeaea; - border: 1px none #c9c3ba; - margin: 0; - text-decoration: none; - - outline: 0; - - padding: 5px 16px 4px 15px; - font-weight: bold; - - border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - -} - -ul.tabs li a.selected, ul.tabs li a:hover -{ - color: #000; - background-color: white; - - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - -moz-border-radius-bottomright: 0; - -moz-border-radius-bottomleft: 0; -} - -ul.tabs li a:hover -{ - background-color: #f1f4ee; -} - -ul.tabs li a.selected -{ - font-weight: bold; - background-color: #525252; - padding-bottom: 5px; - color: white; -} - - -#tabs-body { - position: relative; - overflow: hidden; -} - - -span.tabContent -{ - border: 2px solid #525252; - margin: 0; - padding: 0; - padding-bottom: 10px; -} - -#tabs-body > span { - display: none; -} - -#tabs-body > span.active { - display: block; -} - -.hide -{ - display: none; -} - -.settable -{ - margin: 20px; - border: none; -} -.settable td -{ - border: none; - margin: 0; - padding: 5px; -} - -.settable th{ - padding-bottom: 8px; -} - -.settable.wide td , .settable.wide th { - padding-left: 15px; - padding-right: 15px; -} - - -/*settings navbar*/ -ul.nav { - margin: -30px 0 0; - padding: 0; - list-style: none; - position: absolute; -} - - -ul.nav li { - position: relative; - float: left; - padding: 5px; -} - -ul.nav > li a { - background: white; - -moz-border-radius: 4px 4px 4px 4px; - border: 1px solid #C9C3BA; - border-bottom: medium none; - color: black; -} - -ul.nav ul { - position: absolute; - top: 26px; - left: 10px; - margin: 0; - padding: 0; - list-style: none; - border: 1px solid #AAA; - background: #f1f1f1; - -webkit-box-shadow: 1px 1px 5px #AAA; - -moz-box-shadow: 1px 1px 5px #AAA; - box-shadow: 1px 1px 5px #AAA; - cursor: pointer; -} - -ul.nav .open { - display: block; -} - -ul.nav .close { - display: none; -} - -ul.nav ul li { - float: none; - padding: 0; -} - -ul.nav ul li a { - width: 130px; - background: #f1f1f1; - padding: 3px; - display: block; - font-weight: normal; -} - -ul.nav ul li a:hover { - background: #CDCDCD; -} - -ul.nav ul ul { - left: 137px; - top: 0; -} - -.purr-wrapper{ - margin:10px; -} - -/*Purr alert styles*/ - -.purr-alert{ - margin-bottom:10px; - padding:10px; - background:#000; - font-size:13px; - font-weight:bold; - color:#FFF; - -moz-border-radius:5px; - -webkit-border-radius:5px; - /*-moz-box-shadow: 0 0 10px rgba(255,255,0,.25);*/ - width:300px; -} -.purr-alert.error{ - color:#F55; - padding-left:30px; - background:url(/media/default/img/error.png) no-repeat #000 7px 10px; - width:280px; -} -.purr-alert.success{ - color:#5F5; - padding-left:30px; - background:url(/media/default/img/success.png) no-repeat #000 7px 10px; - width:280px; -} -.purr-alert.notice{ - color:#99F; - padding-left:30px; - background:url(/media/default/img//notice.png) no-repeat #000 7px 10px; - width:280px; -} - -table.system { - border: none; - margin-left: 10px; -} - -table.system td { - border: none -} - -table.system tr > td:first-child { - font-weight: bold; - padding-right: 10px; -}
\ No newline at end of file diff --git a/module/web/media/img/favicon.ico b/module/web/media/img/favicon.ico Binary files differdeleted file mode 100644 index 58b1f4b89..000000000 --- a/module/web/media/img/favicon.ico +++ /dev/null diff --git a/module/web/media/js/MooDialog_static.js b/module/web/media/js/MooDialog_static.js deleted file mode 100644 index d497d3d57..000000000 --- a/module/web/media/js/MooDialog_static.js +++ /dev/null @@ -1,401 +0,0 @@ -/* ---- - -name: Overlay - -authors: - - David Walsh (http://davidwalsh.name) - -license: - - MIT-style license - -requires: [Core/Class, Core/Element.Style, Core/Element.Event, Core/Element.Dimensions, Core/Fx.Tween] - -provides: - - Overlay -... -*/ - -var Overlay = new Class({ - - Implements: [Options, Events], - - options: { - id: 'overlay', - color: '#000', - duration: 500, - opacity: 0.5, - zIndex: 5000/*, - onClick: $empty, - onClose: $empty, - onHide: $empty, - onOpen: $empty, - onShow: $empty - */ - }, - - initialize: function(container, options){ - this.setOptions(options); - this.container = document.id(container); - - this.bound = { - 'window': { - resize: this.resize.bind(this), - scroll: this.scroll.bind(this) - }, - overlayClick: this.overlayClick.bind(this), - tweenStart: this.tweenStart.bind(this), - tweenComplete: this.tweenComplete.bind(this) - }; - - this.build().attach(); - }, - - build: function(){ - this.overlay = new Element('div', { - id: this.options.id, - opacity: 0, - styles: { - position: (Browser.ie6) ? 'absolute' : 'fixed', - background: this.options.color, - left: 0, - top: 0, - 'z-index': this.options.zIndex - } - }).inject(this.container); - this.tween = new Fx.Tween(this.overlay, { - duration: this.options.duration, - link: 'cancel', - property: 'opacity' - }); - this.tween.set('opacity', 0) - return this; - }.protect(), - - attach: function(){ - window.addEvents(this.bound.window); - this.overlay.addEvent('click', this.bound.overlayClick); - this.tween.addEvents({ - onStart: this.bound.tweenStart, - onComplete: this.bound.tweenComplete - }); - return this; - }, - - detach: function(){ - var args = Array.prototype.slice.call(arguments); - args.each(function(item){ - if(item == 'window') window.removeEvents(this.bound.window); - if(item == 'overlay') this.overlay.removeEvent('click', this.bound.overlayClick); - }, this); - return this; - }, - - overlayClick: function(){ - this.fireEvent('click'); - return this; - }, - - tweenStart: function(){ - this.overlay.setStyles({ - width: '100%', - height: this.container.getScrollSize().y - }); - return this; - }, - - tweenComplete: function(){ - this.fireEvent(this.overlay.get('opacity') == this.options.opacity ? 'show' : 'hide'); - return this; - }, - - open: function(){ - this.fireEvent('open'); - this.tween.set('display', 'block'); - this.tween.start(this.options.opacity); - return this; - }, - - close: function(){ - this.fireEvent('close'); - this.tween.start(0).chain(function(){ - this.tween.set('display', 'none'); - }.bind(this)); - return this; - }, - - resize: function(){ - this.fireEvent('resize'); - this.overlay.setStyle('height', this.container.getScrollSize().y); - return this; - }, - - scroll: function(){ - this.fireEvent('scroll'); - if (Browser.ie6) this.overlay.setStyle('left', window.getScroll().x); - return this; - } - -}); -/* ---- -name: MooDialog -description: The base class of MooDialog -authors: Arian Stolwijk -license: MIT-style license -requires: [Core/Class, Core/Element, Core/Element.Styles, Core/Element.Event] -provides: [MooDialog, Element.MooDialog] -... -*/ - - -var MooDialog = new Class({ - - Implements: [Options, Events], - - options: { - 'class': 'MooDialog', - title: null, - scroll: true, // IE - forceScroll: false, - useEscKey: true, - destroyOnHide: true, - autoOpen: true, - closeButton: true, - onInitialize: function(){ - this.wrapper.setStyle('display', 'none'); - }, - onBeforeOpen: function(){ - this.wrapper.setStyle('display', 'block'); - this.fireEvent('show'); - }, - onBeforeClose: function(){ - this.wrapper.setStyle('display', 'none'); - this.fireEvent('hide'); - }/*, - onOpen: function(){}, - onClose: function(){}, - onShow: function(){}, - onHide: function(){}*/ - }, - - initialize: function(options){ - this.setOptions(options); - this.options.inject = this.options.inject || document.body; - options = this.options; - - var wrapper = this.wrapper = new Element('div.' + options['class'].replace(' ', '.')).inject(options.inject); - this.content = new Element('div.content').inject(wrapper); - wrapper.setStyle('display', 'none'); - - if (options.title){ - this.title = new Element('div.title').set('text', options.title).inject(wrapper); - wrapper.addClass('MooDialogTitle'); - } - - if (options.closeButton){ - this.closeButton = new Element('a.close', { - events: {click: this.close.bind(this)} - }).inject(wrapper); - } - - - /*<ie6>*/// IE 6 scroll - if ((options.scroll && Browser.ie6) || options.forceScroll){ - wrapper.setStyle('position', 'absolute'); - var position = wrapper.getPosition(options.inject); - window.addEvent('scroll', function(){ - var scroll = document.getScroll(); - wrapper.setPosition({ - x: position.x + scroll.x, - y: position.y + scroll.y - }); - }); - } - /*</ie6>*/ - - if (options.useEscKey){ - // Add event for the esc key - document.addEvent('keydown', function(e){ - if (e.key == 'esc') this.close(); - }.bind(this)); - } - - this.addEvent('hide', function(){ - if (options.destroyOnHide) this.destroy(); - }.bind(this)); - - this.fireEvent('initialize', wrapper); - }, - - setContent: function(){ - var content = Array.from(arguments); - if (content.length == 1) content = content[0]; - - this.content.empty(); - - var type = typeOf(content); - if (['string', 'number'].contains(type)) this.content.set('text', content); - else this.content.adopt(content); - - return this; - }, - - open: function(){ - this.fireEvent('beforeOpen', this.wrapper).fireEvent('open'); - this.opened = true; - return this; - }, - - close: function(){ - this.fireEvent('beforeClose', this.wrapper).fireEvent('close'); - this.opened = false; - return this; - }, - - destroy: function(){ - this.wrapper.destroy(); - }, - - toElement: function(){ - return this.wrapper; - } - -}); - - -Element.implement({ - - MooDialog: function(options){ - this.store('MooDialog', - new MooDialog(options).setContent(this).open() - ); - return this; - } - -}); -/* ---- -name: MooDialog.Fx -description: Overwrite the default events so the Dialogs are using Fx on open and close -authors: Arian Stolwijk -license: MIT-style license -requires: [Cores/Fx.Tween, Overlay] -provides: MooDialog.Fx -... -*/ - - -MooDialog.implement('options', { - - duration: 400, - closeOnOverlayClick: true, - - onInitialize: function(wrapper){ - this.fx = new Fx.Tween(wrapper, { - property: 'opacity', - duration: this.options.duration - }).set(0); - this.overlay = new Overlay(this.options.inject, { - duration: this.options.duration - }); - if (this.options.closeOnOverlayClick) this.overlay.addEvent('click', this.close.bind(this)); - }, - - onBeforeOpen: function(wrapper){ - this.overlay.open(); - wrapper.setStyle('display', 'block'); - this.fx.start(1).chain(function(){ - this.fireEvent('show'); - }.bind(this)); - }, - - onBeforeClose: function(wrapper){ - this.overlay.close(); - this.fx.start(0).chain(function(){ - this.fireEvent('hide'); - wrapper.setStyle('display', 'none'); - }.bind(this)); - } - -}); -/* ---- -name: MooDialog.Confirm -description: Creates an Confirm Dialog -authors: Arian Stolwijk -license: MIT-style license -requires: MooDialog -provides: [MooDialog.Confirm, Element.confirmLinkClick, Element.confirmFormSubmit] -... -*/ - - -MooDialog.Confirm = new Class({ - - Extends: MooDialog, - - options: { - okText: 'Ok', - cancelText: 'Cancel', - focus: true, - textPClass: 'MooDialogConfirm' - }, - - initialize: function(msg, fn, fn1, options){ - this.parent(options); - var emptyFn = function(){}, - self = this; - - var buttons = [ - {fn: fn || emptyFn, txt: this.options.okText}, - {fn: fn1 || emptyFn, txt: this.options.cancelText} - ].map(function(button){ - return new Element('input[type=button]', { - events: { - click: function(){ - button.fn(); - self.close(); - } - }, - value: button.txt - }); - }); - - this.setContent( - new Element('p.' + this.options.textPClass, {text: msg}), - new Element('div.buttons').adopt(buttons) - ); - if (this.options.autoOpen) this.open(); - - if(this.options.focus) this.addEvent('show', function(){ - buttons[1].focus(); - }); - - } -}); - - -Element.implement({ - - confirmLinkClick: function(msg, options){ - this.addEvent('click', function(e){ - e.stop(); - new MooDialog.Confirm(msg, function(){ - location.href = this.get('href'); - }.bind(this), null, options) - }); - return this; - }, - - confirmFormSubmit: function(msg, options){ - this.addEvent('submit', function(e){ - e.stop(); - new MooDialog.Confirm(msg, function(){ - this.submit(); - }.bind(this), null, options) - }.bind(this)); - return this; - } - -}); diff --git a/module/web/media/js/admin.coffee b/module/web/media/js/admin.coffee deleted file mode 100644 index 82b0dd3ec..000000000 --- a/module/web/media/js/admin.coffee +++ /dev/null @@ -1,58 +0,0 @@ -root = this - -window.addEvent "domready", -> - - root.passwordDialog = new MooDialog {destroyOnHide: false} - root.passwordDialog.setContent $ 'password_box' - - $("login_password_reset").addEvent "click", (e) -> root.passwordDialog.close() - $("login_password_button").addEvent "click", (e) -> - - newpw = $("login_new_password").get("value") - newpw2 = $("login_new_password2").get("value") - - if newpw is newpw2 - form = $("password_form") - form.set "send", { - onSuccess: (data) -> - root.notify.alert "Success", { - 'className': 'success' - } - onFailure: (data) -> - root.notify.alert "Error", { - 'className': 'error' - } - } - - form.send() - - root.passwordDialog.close() - else - alert '{{_("Passwords did not match.")}}' - - e.stop() - - for item in $$(".change_password") - id = item.get("id") - user = id.split("|")[1] - $("user_login").set("value", user) - item.addEvent "click", (e) -> root.passwordDialog.open() - - $('quit-pyload').addEvent "click", (e) -> - new MooDialog.Confirm "{{_('You are really sure you want to quit pyLoad?')}}", -> - new Request.JSON({ - url: '/api/kill' - method: 'get' - }).send() - , -> - e.stop() - - $('restart-pyload').addEvent "click", (e) -> - new MooDialog.Confirm "{{_('Are you sure you want to restart pyLoad?')}}", -> - new Request.JSON({ - url: '/api/restart' - method: 'get' - onSuccess: (data) -> alert "{{_('pyLoad restarted')}}" - }).send() - , -> - e.stop()
\ No newline at end of file diff --git a/module/web/media/js/base.coffee b/module/web/media/js/base.coffee deleted file mode 100644 index 3b5d33e82..000000000 --- a/module/web/media/js/base.coffee +++ /dev/null @@ -1,173 +0,0 @@ -# External scope -root = this - -# helper functions -humanFileSize = (size) -> - filesizename = new Array("B", "KiB", "MiB", "GiB", "TiB", "PiB") - loga = Math.log(size) / Math.log(1024) - i = Math.floor(loga) - a = Math.pow(1024, i) - if size is 0 then "0 B" else (Math.round(size * 100 / a) / 100 + " " + filesizename[i]) - -parseUri = () -> - oldString = $("add_links").value - regxp = new RegExp('(ht|f)tp(s?):\/\/[a-zA-Z0-9\-\.\/\?=_&%#]+[<| |\"|\'|\r|\n|\t]{1}', 'g') - resu = oldString.match regxp - return if resu == null - res = ""; - - for part in resu - if part.indexOf(" ") != -1 - res = res + part.replace(" ", " \n") - else if part.indexOf("\t") != -1 - res = res + part.replace("\t", " \n") - else if part.indexOf("\r") != -1 - res = res + part.replace("\r", " \n") - else if part.indexOf("\"") != -1 - res = res + part.replace("\"", " \n") - else if part.indexOf("<") != -1 - res = res + part.replace("<", " \n") - else if part.indexOf("'") != -1 - res = res + part.replace("'", " \n") - else - res = res + part.replace("\n", " \n") - - $("add_links").value = res; - - -Array::remove = (from, to) -> - rest = this.slice((to || from) + 1 || this.length) - this.length = from < 0 ? this.length + from : from - return [] if this.length == 0 - return this.push.apply(this, rest) - - -document.addEvent "domready", -> - - # global notification - root.notify = new Purr { - 'mode': 'top' - 'position': 'center' - } - - root.captchaBox = new MooDialog {destroyOnHide: false} - root.captchaBox.setContent $ 'cap_box' - - root.addBox = new MooDialog {destroyOnHide: false} - root.addBox.setContent $ 'add_box' - - $('add_form').onsubmit = -> - $('add_form').target = 'upload_target' - if $('add_name').value is "" and $('add_file').value is "" - alert '{{_("Please Enter a packagename.")}}' - return false - else - root.addBox.close() - return true - - $('add_reset').addEvent 'click', -> root.addBox.close() - - $('action_add').addEvent 'click', -> $("add_form").reset(); root.addBox.open() - $('action_play').addEvent 'click', -> new Request({method: 'get', url: '/api/unpauseServer'}).send() - $('action_cancel').addEvent 'click', -> new Request({method: 'get', url: '/api/stopAllDownloads'}).send() - $('action_stop').addEvent 'click', -> new Request({method: 'get', url: '/api/pauseServer'}).send() - - - # captcha events - - $('cap_info').addEvent 'click', -> - load_captcha "get", "" - root.captchaBox.open() - $('cap_reset').addEvent 'click', -> root.captchaBox.close() - $('cap_form').addEvent 'submit', (e) -> - submit_captcha() - e.stop() - - $('cap_positional').addEvent 'click', on_captcha_click - - new Request.JSON({ - url: "/json/status" - onSuccess: LoadJsonToContent - secure: false - async: true - initialDelay: 0 - delay: 4000 - limit: 3000 - }).startTimer() - -LoadJsonToContent = (data) -> - $("speed").set 'text', humanFileSize(data.speed)+"/s" - $("aktiv").set 'text', data.active - $("aktiv_from").set 'text', data.queue - $("aktiv_total").set 'text', data.total - - if data.captcha - if $("cap_info").getStyle("display") != "inline" - $("cap_info").setStyle 'display', 'inline' - root.notify.alert '{{_("New Captcha Request")}}', { - 'className': 'notify' - } - else - $("cap_info").setStyle 'display', 'none' - - - if data.download - $("time").set 'text', ' {{_("on")}}' - $("time").setStyle 'background-color', "#8ffc25" - else - $("time").set 'text', ' {{_("off")}}' - $("time").setStyle 'background-color', "#fc6e26" - - if data.reconnect - $("reconnect").set 'text', ' {{_("on")}}' - $("reconnect").setStyle 'background-color', "#8ffc25" - else - $("reconnect").set 'text', ' {{_("off")}}' - $("reconnect").setStyle 'background-color', "#fc6e26" - - return null - - -set_captcha = (data) -> - $('cap_id').set 'value', data.id - if (data.result_type is 'textual') - $('cap_textual_img').set 'src', data.src - $('cap_title').set 'text', '{{_("Please read the text on the captcha.")}}' - $('cap_submit').setStyle 'display', 'inline' - $('cap_textual').setStyle 'display', 'block' - $('cap_positional').setStyle 'display', 'none' - - else if (data.result_type == 'positional') - $('cap_positional_img').set('src', data.src) - $('cap_title').set('text', '{{_("Please click on the right captcha position.")}}') - $('cap_submit').setStyle('display', 'none') - $('cap_textual').setStyle('display', 'none') - - -load_captcha = (method, post) -> - new Request.JSON({ - url: "/json/set_captcha" - onSuccess: (data) -> set_captcha(data) if data.captcha else clear_captcha() - secure: false - async: true - method: method - }).send(post) - -clear_captcha = -> - $('cap_textual').setStyle 'display', 'none' - $('cap_textual_img').set 'src', '' - $('cap_positional').setStyle 'display', 'none' - $('cap_positional_img').set 'src', '' - $('cap_title').set 'text', '{{_("No Captchas to read.")}}' - -submit_captcha = -> - load_captcha("post", "cap_id=" + $('cap_id').get('value') + "&cap_result=" + $('cap_result').get('value') ); - $('cap_result').set('value', '') - false - -on_captcha_click = (e) -> - position = e.target.getPosition() - x = e.page.x - position.x - y = e.page.y - position.y - $('cap_result').value = x + "," + y - submit_captcha()
\ No newline at end of file diff --git a/module/web/media/js/settings.coffee b/module/web/media/js/settings.coffee deleted file mode 100644 index 9205233e3..000000000 --- a/module/web/media/js/settings.coffee +++ /dev/null @@ -1,107 +0,0 @@ -root = this - -window.addEvent 'domready', -> - root.accountDialog = new MooDialog {destroyOnHide: false} - root.accountDialog.setContent $ 'account_box' - - new TinyTab $$('#toptabs li a'), $$('#tabs-body > span') - - $$('ul.nav').each (nav) -> - new MooDropMenu nav, { - onOpen: (el) -> el.fade 'in' - onClose: (el) -> el.fade 'out' - onInitialize: (el) -> el.fade('hide').set 'tween', {duration:500} - } - - new SettingsUI() - - -class SettingsUI - constructor: -> - @menu = $$ "#general-menu li" - @menu.append $$ "#plugin-menu li" - - @name = $ "tabsback" - @general = $ "general_form_content" - @plugin = $ "plugin_form_content" - - el.addEvent 'click', @menuClick.bind(this) for el in @menu - - $("general|submit").addEvent "click", @configSubmit.bind(this) - $("plugin|submit").addEvent "click", @configSubmit.bind(this) - - $("account_add").addEvent "click", (e) -> - root.accountDialog.open() - e.stop() - - $("account_reset").addEvent "click", (e) -> - root.accountDialog.close() - - $("account_add_button").addEvent "click", @addAccount.bind(this) - $("account_submit").addEvent "click", @submitAccounts.bind(this) - - - menuClick: (e) -> - [category, section] = e.target.get("id").split("|") - name = e.target.get "text" - - - target = if category is "general" then @general else @plugin - target.dissolve() - - new Request({ - "method" : "get" - "url" : "/json/load_config/#{category}/#{section}" - "onSuccess": (data) => - target.set "html", data - target.reveal() - this.name.set "text", name - }).send() - - - configSubmit: (e) -> - category = e.target.get("id").split("|")[0]; - form = $("#{category}_form"); - - form.set "send", { - "method": "post" - "url": "/json/save_config/#{category}" - "onSuccess" : -> - root.notify.alert '{{ _("Settings saved.")}}', { - 'className': 'success' - } - "onFailure": -> - root.notify.alert '{{ _("Error occured.")}}', { - 'className': 'error' - } - } - form.send() - e.stop() - - addAccount: (e) -> - form = $ "add_account_form" - form.set "send", { - "method": "post" - "onSuccess" : -> window.location.reload() - "onFailure": -> - root.notify.alert '{{_("Error occured.")}}', { - 'className': 'error' - } - } - - form.send() - e.stop() - - submitAccounts: (e) -> - form = $ "account_form" - form.set "send", { - "method": "post", - "onSuccess" : -> window.location.reload() - "onFailure": -> - root.notify.alert('{{ _("Error occured.") }}', { - 'className': 'error' - }); - } - - form.send() - e.stop()
\ No newline at end of file diff --git a/module/web/templates/500.html b/module/web/templates/500.html deleted file mode 100644 index e15090b66..000000000 --- a/module/web/templates/500.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" - "http://www.w3.org/TR/html4/loose.dtd"> -<html> -<head> - <title>Server Error</title> -</head> -<body> -<h1>Server Error occured. Please enable debug mode to get a more detailed report.</h1> -</body> -</html> diff --git a/module/web/templates/default/captcha.html b/module/web/templates/default/captcha.html deleted file mode 100644 index 288375b76..000000000 --- a/module/web/templates/default/captcha.html +++ /dev/null @@ -1,42 +0,0 @@ -<!-- Captcha box --> -<div id="cap_box" class="window_box"> - - <form id="cap_form" action="/json/set_captcha" method="POST" enctype="multipart/form-data" onsubmit="return false;"> - - <h1>{{_("Captcha reading")}}</h1> - <p id="cap_title">{{_("Please read the text on the captcha.")}}</p> - - <div id="cap_textual"> - - <input id="cap_id" name="cap_id" type="hidden" value="" /> - - <label>{{_("Captcha")}} - <span class="small">{{_("The captcha.")}}</span> - </label> - <span class="cont"> - <img id="cap_textual_img" src=""> - </span> - - <label>{{_("Text")}} - <span class="small">{{_("Input the text on the captcha.")}}</span> - </label> - <input id="cap_result" name="cap_result" type="text" size="20" /> - - </div> - - <div id="cap_positional" style="text-align: center"> - <img id="cap_positional_img" src="" style="margin: 10px; cursor:pointer"> - </div> - - <div id="button_bar" style="text-align: center"> - <span> - <button id="cap_submit" type="submit" style="margin-left: 0">{{_("Submit")}}</button> - <button id="cap_reset" type="reset" style="margin-left: 0">{{_("Close")}}</button> - </span> - </div> - - <div class="spacer"></div> - - </form> - -</div>
\ No newline at end of file diff --git a/module/web/templates/default/folder.html b/module/web/templates/default/folder.html deleted file mode 100644 index b385e80cb..000000000 --- a/module/web/templates/default/folder.html +++ /dev/null @@ -1,15 +0,0 @@ -<li class="folder"> - <input type="hidden" name="path" class="path" value="{{ path }}" /> - <input type="hidden" name="name" class="name" value="{{ name }}" /> - <span> - <b>{{ name }}</b> - <span class="buttons" style="opacity:0"> - <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/media/default/img/pencil.png" /> - - <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/media/default/img/delete.png" /> - - <img title="{{_("Add subdirectory")}}" class="mkdir" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/media/default/img/add_folder.png" /> - </span> - </span> - <div style="display:none">{{ _("Folder is empty") }}</div> -</li>
\ No newline at end of file diff --git a/module/web/templates/default/setup.html b/module/web/templates/default/setup.html deleted file mode 100644 index 39ef6f1e8..000000000 --- a/module/web/templates/default/setup.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'default/base.html' %} - -{% block title %}{{ _("Setup") }} - {{ super() }} {% endblock %} -{% block subtitle %}{{ _("Setup") }}{% endblock %} -{% block headpanel %}Welcome to pyLoad{% endblock %} -{% block menu %} - <li style="height: 25px"> <!-- Needed to get enough margin --> - </li> -{% endblock %} - -{% block content %} - Comming Soon. -{% endblock %}
\ No newline at end of file diff --git a/module/web/webinterface.py b/module/webui/__init__.py index ec8b2e56c..85fec1b52 100644 --- a/module/web/webinterface.py +++ b/module/webui/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -24,8 +23,8 @@ import os from os.path import join, abspath, dirname, exists from os import makedirs -PROJECT_DIR = abspath(dirname(__file__)) -PYLOAD_DIR = abspath(join(PROJECT_DIR, "..", "..")) +THEME_DIR = abspath(join(dirname(__file__), "themes")) +PYLOAD_DIR = abspath(join(THEME_DIR, "..", "..", "..")) sys.path.append(PYLOAD_DIR) @@ -41,7 +40,7 @@ from middlewares import StripPathMiddleware, GZipMiddleWare, PrefixMiddleware SETUP = None PYLOAD = None -from module.web import ServerThread +from module.threads import ServerThread if not ServerThread.core: if ServerThread.setup: @@ -57,7 +56,7 @@ from module.common.JsEngine import JsEngine JS = JsEngine() -TEMPLATE = config.get('webinterface', 'template') +THEME = config.get('webinterface', 'theme') DL_ROOT = config.get('general', 'download_folder') LOG_ROOT = config.get('log', 'log_folder') PREFIX = config.get('webinterface', 'prefix') @@ -75,13 +74,11 @@ if not exists(cache): makedirs(cache) bcc = FileSystemBytecodeCache(cache, '%s.cache') -loader = PrefixLoader({ - "default": FileSystemLoader(join(PROJECT_DIR, "templates", "default")), - 'js': FileSystemLoader(join(PROJECT_DIR, 'media', 'js')) -}) + +loader = FileSystemLoader(THEME_DIR) env = Environment(loader=loader, extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'], trim_blocks=True, auto_reload=False, - bytecode_cache=bcc) + bytecode_cache=bcc) from filters import quotepath, path_make_relative, path_make_absolute, truncate, date @@ -120,17 +117,14 @@ web = GZipMiddleWare(web) if PREFIX: web = PrefixMiddleware(web, prefix=PREFIX) -import pyload_app -import json_app -import cnl_app -import api_app +import module.webui.app def run_simple(host="0.0.0.0", port="8000"): run(app=web, host=host, port=port, quiet=True) def run_lightweight(host="0.0.0.0", port="8000"): - run(app=web, host=host, port=port, quiet=True, server="bjoern") + run(app=web, host=host, port=port, server="bjoern", quiet=True) def run_threaded(host="0.0.0.0", port="8000", theads=3, cert="", key=""): @@ -142,7 +136,7 @@ def run_threaded(host="0.0.0.0", port="8000", theads=3, cert="", key=""): CherryPyWSGIServer.numthreads = theads - from utils import CherryPyWSGI + from module.webui.app.utils import CherryPyWSGI run(app=web, host=host, port=port, server=CherryPyWSGI, quiet=True) @@ -151,7 +145,3 @@ def run_fcgi(host="0.0.0.0", port="8000"): from bottle import FlupFCGIServer run(app=web, host=host, port=port, server=FlupFCGIServer, quiet=True) - - -if __name__ == "__main__": - run(app=web, port=8001) diff --git a/module/webui/app/__init__.py b/module/webui/app/__init__.py new file mode 100644 index 000000000..e52102840 --- /dev/null +++ b/module/webui/app/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from module.webui.app import api, cnl, json, pyload diff --git a/module/web/api_app.py b/module/webui/app/api.py index 1629c1677..ba178682a 100644 --- a/module/web/api_app.py +++ b/module/webui/app/api.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- from urllib import unquote @@ -8,7 +7,7 @@ from traceback import format_exc, print_exc from bottle import route, request, response, HTTPError from utils import toDict, set_session -from webinterface import PYLOAD +from module.webui import PYLOAD from module.common.json_layer import json from module.lib.SafeEval import const_eval as literal_eval @@ -25,8 +24,8 @@ class TBaseEncoder(json.JSONEncoder): # accepting positional arguments, as well as kwargs via post and get -@route("/api/:func:args#[a-zA-Z0-9\-_/\"'\[\]%{}]*#") -@route("/api/:func:args#[a-zA-Z0-9\-_/\"'\[\]%{}]*#", method="POST") +@route('/api/<func><args:re:[a-zA-Z0-9\-_/\"\'\[\]%{}]*>') +@route('/api/<func><args:re:[a-zA-Z0-9\-_/\"\'\[\]%{}]*>', method='POST') def call_api(func, args=""): response.headers.replace("Content-type", "application/json") response.headers.append("Cache-Control", "no-cache, must-revalidate") @@ -70,7 +69,7 @@ def callApi(func, *args, **kwargs): #post -> username, password -@route("/api/login", method="POST") +@route('/api/login', method='POST') def login(): response.headers.replace("Content-type", "application/json") response.headers.append("Cache-Control", "no-cache, must-revalidate") @@ -93,7 +92,7 @@ def login(): return json.dumps(True) -@route("/api/logout") +@route('/api/logout') def logout(): response.headers.replace("Content-type", "application/json") response.headers.append("Cache-Control", "no-cache, must-revalidate") diff --git a/module/web/cnl_app.py b/module/webui/app/cnl.py index d8f7c1180..b29013d82 100644 --- a/module/web/cnl_app.py +++ b/module/webui/app/cnl.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- from os.path import join import re @@ -7,7 +6,8 @@ from base64 import standard_b64decode from binascii import unhexlify from bottle import route, request, HTTPError -from webinterface import PYLOAD, DL_ROOT, JS +from module.webui import PYLOAD, DL_ROOT, JS + try: from Crypto.Cipher import AES @@ -17,8 +17,8 @@ except: def local_check(function): def _view(*args, **kwargs): - if request.environ.get('REMOTE_ADDR', "0") in ('127.0.0.1', 'localhost') \ - or request.environ.get('HTTP_HOST','0') == '127.0.0.1:9666': + if request.environ.get("REMOTE_ADDR", "0") in ("127.0.0.1", "localhost") \ + or request.environ.get("HTTP_HOST", "0") in ("127.0.0.1:9666", "localhost:9666"): return function(*args, **kwargs) else: return HTTPError(403, "Forbidden") @@ -26,14 +26,15 @@ def local_check(function): return _view -@route("/flash") -@route("/flash/:id") -@route("/flash", method="POST") +@route('/flash') +@route('/flash/<id>') +@route('/flash', method='POST') @local_check def flash(id="0"): return "JDownloader\r\n" -@route("/flash/add", method="POST") + +@route('/flash/add', method='POST') @local_check def add(request): package = request.POST.get('referer', None) @@ -46,10 +47,10 @@ def add(request): return "" -@route("/flash/addcrypted", method="POST") + +@route('/flash/addcrypted', method='POST') @local_check def addcrypted(): - package = request.forms.get('referer', 'ClickAndLoad Package') dlc = request.forms['crypted'].replace(" ", "+") @@ -65,10 +66,10 @@ def addcrypted(): else: return "success\r\n" -@route("/flash/addcrypted2", method="POST") + +@route('/flash/addcrypted2', method='POST') @local_check def addcrypted2(): - package = request.forms.get("source", None) crypted = request.forms["crypted"] jk = request.forms["jk"] @@ -82,7 +83,7 @@ def addcrypted2(): try: jk = re.findall(r"return ('|\")(.+)('|\")", jk)[0][1] except: - ## Test for some known js functions to decode + ## Test for some known js functions to decode if jk.find("dec") > -1 and jk.find("org") > -1: org = re.findall(r"var org = ('|\")([^\"']+)", jk)[0][1] jk = list(org) @@ -100,7 +101,7 @@ def addcrypted2(): IV = Key obj = AES.new(Key, AES.MODE_CBC, IV) - result = obj.decrypt(crypted).replace("\x00", "").replace("\r","").split("\n") + result = obj.decrypt(crypted).replace("\x00", "").replace("\r", "").split("\n") result = filter(lambda x: x != "", result) @@ -114,13 +115,15 @@ def addcrypted2(): else: return "success\r\n" -@route("/flashgot_pyload") -@route("/flashgot_pyload", method="POST") -@route("/flashgot") -@route("/flashgot", method="POST") + +@route('/flashgot_pyload') +@route('/flashgot_pyload', method='POST') +@route('/flashgot') +@route('/flashgot', method='POST') @local_check def flashgot(): - if request.environ['HTTP_REFERER'] != "http://localhost:9666/flashgot" and request.environ['HTTP_REFERER'] != "http://127.0.0.1:9666/flashgot": + if request.environ['HTTP_REFERER'] != "http://localhost:9666/flashgot" and \ + request.environ['HTTP_REFERER'] != "http://127.0.0.1:9666/flashgot": return HTTPError() autostart = int(request.forms.get('autostart', 0)) @@ -135,7 +138,8 @@ def flashgot(): return "" -@route("/crossdomain.xml") + +@route('/crossdomain.xml') @local_check def crossdomain(): rep = "<?xml version=\"1.0\"?>\n" @@ -146,17 +150,17 @@ def crossdomain(): return rep -@route("/flash/checkSupportForUrl") +@route('/flash/checkSupportForUrl') @local_check def checksupport(): - url = request.GET.get("url") res = PYLOAD.checkURLs([url]) supported = (not res[0][1] is None) return str(supported).lower() -@route("/jdcheck.js") + +@route('/jdcheck.js') @local_check def jdcheck(): rep = "jdownloader=true;\n" diff --git a/module/web/json_app.py b/module/webui/app/json.py index f3626405c..cf9a8f238 100644 --- a/module/web/json_app.py +++ b/module/webui/app/json.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- from os.path import join @@ -7,7 +6,7 @@ from shutil import copyfileobj from bottle import route, request, HTTPError -from webinterface import PYLOAD +from module.webui import PYLOAD from utils import login_required, render_to_response, toDict @@ -26,8 +25,8 @@ def get_sort_key(item): return item["order"] -@route("/json/status") -@route("/json/status", method="POST") +@route('/json/status') +@route('/json/status', method='POST') @login_required('LIST') def status(): try: @@ -38,8 +37,8 @@ def status(): return HTTPError() -@route("/json/links") -@route("/json/links", method="POST") +@route('/json/links') +@route('/json/links', method='POST') @login_required('LIST') def links(): try: @@ -65,7 +64,7 @@ def links(): return HTTPError() -@route("/json/packages") +@route('/json/packages') @login_required('LIST') def packages(): print "/json/packages" @@ -83,7 +82,7 @@ def packages(): return HTTPError() -@route("/json/package/<id:int>") +@route('/json/package/<id:int>') @login_required('LIST') def package(id): try: @@ -118,7 +117,7 @@ def package(id): return HTTPError() -@route("/json/package_order/:ids") +@route('/json/package_order/<ids>') @login_required('ADD') def package_order(ids): try: @@ -129,7 +128,7 @@ def package_order(ids): return HTTPError() -@route("/json/abort_link/<id:int>") +@route('/json/abort_link/<id:int>') @login_required('DELETE') def abort_link(id): try: @@ -139,7 +138,7 @@ def abort_link(id): return HTTPError() -@route("/json/link_order/:ids") +@route('/json/link_order/<ids>') @login_required('ADD') def link_order(ids): try: @@ -150,8 +149,8 @@ def link_order(ids): return HTTPError() -@route("/json/add_package") -@route("/json/add_package", method="POST") +@route('/json/add_package') +@route('/json/add_package', method='POST') @login_required('ADD') def add_package(): name = request.forms.get("add_name", "New Package").strip() @@ -186,7 +185,7 @@ def add_package(): PYLOAD.setPackageData(pack, data) -@route("/json/move_package/<dest:int>/<id:int>") +@route('/json/move_package/<dest:int>/<id:int>') @login_required('MODIFY') def move_package(dest, id): try: @@ -196,7 +195,7 @@ def move_package(dest, id): return HTTPError() -@route("/json/edit_package", method="POST") +@route('/json/edit_package', method='POST') @login_required('MODIFY') def edit_package(): try: @@ -212,8 +211,8 @@ def edit_package(): return HTTPError() -@route("/json/set_captcha") -@route("/json/set_captcha", method="POST") +@route('/json/set_captcha') +@route('/json/set_captcha', method='POST') @login_required('ADD') def set_captcha(): if request.environ.get('REQUEST_METHOD', "GET") == "POST": @@ -232,7 +231,7 @@ def set_captcha(): return {'captcha': False} -@route("/json/load_config/:category/:section") +@route('/json/load_config/<category>/<section>') @login_required("SETTINGS") def load_config(category, section): conf = None @@ -242,7 +241,7 @@ def load_config(category, section): conf = PYLOAD.getPluginConfigDict() for key, option in conf[section].iteritems(): - if key in ("desc","outline"): continue + if key in ("desc", "outline"): continue if ";" in option["type"]: option["list"] = option["type"].split(";") @@ -252,7 +251,7 @@ def load_config(category, section): return render_to_response("settings_item.html", {"skey": section, "section": conf[section]}) -@route("/json/save_config/:category", method="POST") +@route('/json/save_config/<category>', method='POST') @login_required("SETTINGS") def save_config(category): for key, value in request.POST.iteritems(): @@ -266,7 +265,7 @@ def save_config(category): PYLOAD.setConfigValue(section, option, decode(value), category) -@route("/json/add_account", method="POST") +@route('/json/add_account', method='POST') @login_required("ACCOUNTS") def add_account(): login = request.POST["account_login"] @@ -276,7 +275,7 @@ def add_account(): PYLOAD.updateAccount(type, login, password) -@route("/json/update_accounts", method="POST") +@route('/json/update_accounts', method='POST') @login_required("ACCOUNTS") def update_accounts(): deleted = [] #dont update deleted accs or they will be created again @@ -284,7 +283,7 @@ def update_accounts(): for name, value in request.POST.iteritems(): value = value.strip() if not value: continue - + tmp, user = name.split(";") plugin, action = tmp.split("|") @@ -300,7 +299,7 @@ def update_accounts(): deleted.append((plugin,user)) PYLOAD.removeAccount(plugin, user) -@route("/json/change_password", method="POST") +@route('/json/change_password', method='POST') def change_password(): user = request.POST["user_login"] diff --git a/module/web/pyload_app.py b/module/webui/app/pyload.py index df4a4b3d4..8864688f9 100644 --- a/module/web/pyload_app.py +++ b/module/webui/app/pyload.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -27,16 +26,16 @@ from os.path import isdir, isfile, join, abspath from sys import getfilesystemencoding from urllib import unquote -from bottle import route, static_file, request, response, redirect, HTTPError, error +from bottle import route, static_file, request, response, redirect, error -from webinterface import PYLOAD, PYLOAD_DIR, PROJECT_DIR, SETUP, env +from module.webui import PYLOAD, PYLOAD_DIR, THEME_DIR, SETUP, env from utils import render_to_response, parse_permissions, parse_userdata, \ login_required, get_permission, set_permission, permlist, toDict, set_session -from filters import relpath, unquotepath +from module.webui.filters import relpath, unquotepath -from module.utils import formatSize, save_join, fs_encode, fs_decode +from module.utils import formatSize, safe_join, fs_encode, fs_decode # Helper @@ -55,8 +54,10 @@ def pre_processor(): # check if update check is available if info: - if info["pyload"] == "True": update = True - if info["plugins"] == "True": plugins = True + if info["pyload"] == "True": + update = info["version"] + if info["plugins"] == "True": + plugins = True return {"user": user, @@ -73,43 +74,63 @@ def base(messages): ## Views +@error(403) +def error403(code): + return "The parameter you passed has the wrong format" + + +@error(404) +def error404(code): + return "Sorry, this page does not exist" + + @error(500) def error500(error): - print "An error occured while processing the request." - if error.traceback: - print error.traceback - + traceback = error.traceback + if traceback: + print traceback return base(["An Error occured, please enable debug mode to get more details.", error, - error.traceback.replace("\n", "<br>") if error.traceback else "No Traceback"]) + traceback.replace("\n", "<br>") if traceback else "No Traceback"]) -# render js -@route("/media/js/<path:re:.+\.js>") -def js_dynamic(path): - response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", - time.gmtime(time.time() + 60 * 60 * 24 * 2)) - response.headers['Cache-control'] = "public" + +@route('/<theme>/<file:re:(.+/)?[^/]+\.min\.[^/]+>') +def server_min(theme, file): + filename = join(THEME_DIR, theme, file) + if not isfile(filename): + file = file.replace(".min.", ".") + if file.endswith(".js"): + return server_js(theme, file) + else: + return server_static(theme, file) + + +@route('/<theme>/<file_static:re:.+\.js>') +def server_js(theme, file): response.headers['Content-Type'] = "text/javascript; charset=UTF-8" - try: - # static files are not rendered - if "static" not in path and "mootools" not in path: - t = env.get_template("js/%s" % path) - return t.render() - else: - return static_file(path, root=join(PROJECT_DIR, "media", "js")) - except: - return HTTPError(404, "Not Found") + if "/render/" in file or ".render." in file: + response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", + time.gmtime(time.time() + 24 * 7 * 60 * 60)) + response.headers['Cache-control'] = "public" -@route('/media/<path:path>') -def server_static(path): + path = join(theme, file) + return env.get_template(path).render() + else: + return server_static(theme, file) + + +@route('/<theme>/<file:path>') +def server_static(theme, file): response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", - time.gmtime(time.time() + 60 * 60 * 24 * 7)) + time.gmtime(time.time() + 24 * 7 * 60 * 60)) response.headers['Cache-control'] = "public" - return static_file(path, root=join(PROJECT_DIR, "media")) + + return static_file(file, root=join(THEME_DIR, theme)) + @route('/favicon.ico') def favicon(): - return static_file("favicon.ico", root=join(PROJECT_DIR, "media", "img")) + return static_file("icon.ico", root=join(PYLOAD_DIR, "docs", "resources")) @route('/login', method="GET") @@ -125,7 +146,7 @@ def nopermission(): return base([_("You dont have permission to access this page.")]) -@route("/login", method="POST") +@route('/login', method='POST') def login_post(): user = request.forms.get("username") password = request.forms.get("password") @@ -139,15 +160,15 @@ def login_post(): return redirect("/") -@route("/logout") +@route('/logout') def logout(): s = request.environ.get('beaker.session') s.delete() return render_to_response("logout.html", proc=[pre_processor]) -@route("/") -@route("/home") +@route('/') +@route('/home') @login_required("LIST") def home(): try: @@ -164,7 +185,7 @@ def home(): return render_to_response("home.html", {"res": res}, [pre_processor]) -@route("/queue") +@route('/queue') @login_required("LIST") def queue(): queue = PYLOAD.getQueue() @@ -174,7 +195,7 @@ def queue(): return render_to_response('queue.html', {'content': queue, 'target': 1}, [pre_processor]) -@route("/collector") +@route('/collector') @login_required('LIST') def collector(): queue = PYLOAD.getCollector() @@ -184,7 +205,7 @@ def collector(): return render_to_response('queue.html', {'content': queue, 'target': 0}, [pre_processor]) -@route("/downloads") +@route('/downloads') @login_required('DOWNLOAD') def downloads(): root = PYLOAD.getConfigValue("general", "download_folder") @@ -199,16 +220,16 @@ def downloads(): items = listdir(fs_encode(root)) for item in sorted([fs_decode(x) for x in items]): - if isdir(save_join(root, item)): + if isdir(safe_join(root, item)): folder = { 'name': item, 'path': item, 'files': [] } - files = listdir(save_join(root, item)) + files = listdir(safe_join(root, item)) for file in sorted([fs_decode(x) for x in files]): try: - if isfile(save_join(root, item, file)): + if isfile(safe_join(root, item, file)): folder['files'].append(file) except: pass @@ -220,7 +241,7 @@ def downloads(): return render_to_response('downloads.html', {'files': data}, [pre_processor]) -@route("/downloads/get/<path:re:.+>") +@route('/downloads/get/<path:path>') @login_required("DOWNLOAD") def get_download(path): path = unquote(path).decode("utf8") @@ -229,16 +250,11 @@ def get_download(path): root = PYLOAD.getConfigValue("general", "download_folder") path = path.replace("..", "") - try: - return static_file(fs_encode(path), fs_encode(root)) - - except Exception, e: - print e - return HTTPError(404, "File not Found.") + return static_file(fs_encode(path), fs_encode(root)) -@route("/settings") +@route('/settings') @login_required('SETTINGS') def config(): conf = PYLOAD.getConfig() @@ -269,13 +285,12 @@ def config(): data.validuntil = _("not available") else: t = time.localtime(data.validuntil) - data.validuntil = time.strftime("%d.%m.%Y", t) + data.validuntil = time.strftime("%d.%m.%Y - %H:%M:%S", t) - if "time" in data.options: - try: - data.options["time"] = data.options["time"][0] - except: - data.options["time"] = "0:00-0:00" + try: + data.options["time"] = data.options["time"][0] + except: + data.options["time"] = "0:00-0:00" if "limitDL" in data.options: data.options["limitdl"] = data.options["limitDL"][0] @@ -287,10 +302,10 @@ def config(): [pre_processor]) -@route("/filechooser") -@route("/pathchooser") -@route("/filechooser/:file#.+#") -@route("/pathchooser/:path#.+#") +@route('/filechooser') +@route('/pathchooser') +@route('/filechooser/<file:path>') +@route('/pathchooser/<path:path>') @login_required('STATUS') def path(file="", path=""): if file: @@ -377,10 +392,10 @@ def path(file="", path=""): 'absolute': abs}, []) -@route("/logs") -@route("/logs", method="POST") -@route("/logs/:item") -@route("/logs/:item", method="POST") +@route('/logs') +@route('/logs', method='POST') +@route('/logs/<item>') +@route('/logs/<item>', method='POST') @login_required('LOGS') def logs(item=-1): s = request.environ.get('beaker.session') @@ -389,7 +404,7 @@ def logs(item=-1): reversed = s.get('reversed', False) warning = "" - conf = PYLOAD.getConfigValue("log","file_log") + conf = PYLOAD.getConfigValue("log", "file_log") if not conf: warning = "Warning: File log is disabled, see settings page." @@ -461,11 +476,11 @@ def logs(item=-1): 'reversed': reversed, 'perpage': perpage, 'perpage_p': sorted(perpage_p), 'iprev': 1 if item - perpage < 1 else item - perpage, 'inext': (item + perpage) if item + perpage < len(log) else item}, - [pre_processor]) + [pre_processor]) -@route("/admin") -@route("/admin", method="POST") +@route('/admin') +@route('/admin', method='POST') @login_required("ADMIN") def admin(): # convert to dict @@ -492,7 +507,6 @@ def admin(): for perm in perms: user[name]["perms"][perm] = False - for perm in request.POST.getall("%s|perms" % name): user[name]["perms"][perm] = True @@ -503,15 +517,12 @@ def admin(): return render_to_response("admin.html", {"users": user, "permlist": perms}, [pre_processor]) -@route("/setup") +@route('/setup') def setup(): - if PYLOAD or not SETUP: - return base([_("Run pyLoadCore.py -s to access the setup.")]) - - return render_to_response('setup.html', {"user": False, "perms": False}) + return base([_("Run pyload.py -s to access the setup.")]) -@route("/info") +@route('/info') def info(): conf = PYLOAD.getConfigDict() diff --git a/module/web/utils.py b/module/webui/app/utils.py index a89c87558..1ba08e9a7 100644 --- a/module/web/utils.py +++ b/module/webui/app/utils.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify @@ -16,18 +15,20 @@ @author: RaNaN """ + +from os.path import join + from bottle import request, HTTPError, redirect, ServerAdapter -from webinterface import env, TEMPLATE +from module.webui import env, THEME from module.Api import has_permission, PERMS, ROLE -def render_to_response(name, args={}, proc=[]): +def render_to_response(file, args={}, proc=[]): for p in proc: args.update(p()) - - t = env.get_template(TEMPLATE + "/" + name) - return t.render(**args) + path = join(THEME, "tml", file) + return env.get_template(path).render(**args) def parse_permissions(session): diff --git a/module/web/filters.py b/module/webui/filters.py index 13b8345fc..c5e9447ee 100644 --- a/module/web/filters.py +++ b/module/webui/filters.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- import os from os.path import abspath, commonprefix, join @@ -59,4 +58,4 @@ def truncate(value, n): return value def date(date, format): - return date
\ No newline at end of file + return date diff --git a/module/web/middlewares.py b/module/webui/middlewares.py index e0e6c3102..5f56f81ee 100644 --- a/module/web/middlewares.py +++ b/module/webui/middlewares.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- import gzip @@ -130,4 +129,4 @@ class GzipResponse(object): content_length = self.buffer.tell() update_header(self.headers, "Content-Length" , str(content_length)) - self.start_response(self.status, self.headers)
\ No newline at end of file + self.start_response(self.status, self.headers) diff --git a/module/web/servers/lighttpd_default.conf b/module/webui/servers/lighttpd_default.conf index e56dda35f..bbeb5f7a7 100644 --- a/module/web/servers/lighttpd_default.conf +++ b/module/webui/servers/lighttpd_default.conf @@ -150,4 +150,4 @@ url.rewrite-once = ( "^(/.*)$" => "/pyload.fcgi$1", ) -%(ssl)
\ No newline at end of file +%(ssl) diff --git a/module/web/servers/nginx_default.conf b/module/webui/servers/nginx_default.conf index b4ebd1e02..b4ebd1e02 100644 --- a/module/web/servers/nginx_default.conf +++ b/module/webui/servers/nginx_default.conf diff --git a/module/webui/themes/dark/css/MooDialog.css b/module/webui/themes/dark/css/MooDialog.css new file mode 100644 index 000000000..dd0c0a601 --- /dev/null +++ b/module/webui/themes/dark/css/MooDialog.css @@ -0,0 +1,94 @@ +/* Created by Arian Stolwijk <http://www.aryweb.nl> */ + +.MooDialog { +/* position: fixed;*/ + margin: 0 auto 0 -350px; + width:600px; + padding:14px; + left:50%; + top: 100px; + color:white; + + position: absolute; + left: 50%; + z-index: 50000; + + background: url(../img/dark-bg.jpg); + color: black; + border-radius: 7px; + -moz-border-radius: 7px; + -webkit-border-radius: 7px; + border-radius: 7px; + -moz-box-shadow: 1px 1px 5px rgba(0,0,0,0.8); + -webkit-box-shadow: 1px 1px 5px rgba(0,0,0,0.8); + box-shadow: 1px 1px 5px rgba(0,0,0,0.8); +} + +.MooDialogTitle { + padding-top: 30px; +} + +.MooDialog .title { + position: absolute; + top: 0; + left: 0; + right: 0; + padding: 3px 20px; + background: #b7c4dc; + border-bottom: 1px solid #a1aec5; + font-weight: bold; + text-shadow: 1px 1px 0 #fff; + color: black; + border-radius: 7px; + -moz-border-radius: 7px; + -webkit-border-radius: 7px; +} + +.MooDialog .close { + background: url(../img/MooDialog/dialog-close.png) no-repeat; + width: 16px; + height: 16px; + display: block; + cursor: pointer; + top: -5px; + left: -5px; + position: absolute; +} + +.MooDialog .buttons { + text-align: right; + margin: 0; + padding: 0; + border: 0; + background: none; +} + +.MooDialog .iframe { + width: 100%; + height: 100%; +} + +.MooDialog .textInput { + width: 200px; + float: left; + color:white; +} + +.MooDialog .MooDialogAlert, +.MooDialog .MooDialogConfirm, +.MooDialog .MooDialogPrompt, +.MooDialog .MooDialogError { + background: url(../img/MooDialog/dialog-warning.png) no-repeat; + padding-left: 40px; + min-height: 40px; + color:white; +} + +.MooDialog .MooDialogConfirm, +.MooDialog .MooDialogPromt { + background: url(../img/MooDialog/dialog-question.png) no-repeat; +} + +.MooDialog .MooDialogError { + background: url(../img/MooDialog/dialog-error.png) no-repeat; +} diff --git a/module/webui/themes/dark/css/dark.css b/module/webui/themes/dark/css/dark.css new file mode 100644 index 000000000..ca16d0621 --- /dev/null +++ b/module/webui/themes/dark/css/dark.css @@ -0,0 +1,962 @@ +.hidden { + display:none; +} +.leftalign { + text-align:left; +} +.centeralign { + text-align:center; +} +.rightalign { + text-align:right; +} + + +.dokuwiki div.plugin_translation ul li a.wikilink1:link, .dokuwiki div.plugin_translation ul li a.wikilink1:hover, .dokuwiki div.plugin_translation ul li a.wikilink1:active, .dokuwiki div.plugin_translation ul li a.wikilink1:visited { + background-color:#000080; + color:#fff !important; + text-decoration:none; + padding:0 0.2em; + margin:0.1em 0.2em; + border:none !important; +} +.dokuwiki div.plugin_translation ul li a.wikilink2:link, .dokuwiki div.plugin_translation ul li a.wikilink2:hover, .dokuwiki div.plugin_translation ul li a.wikilink2:active, .dokuwiki div.plugin_translation ul li a.wikilink2:visited { + background-color:#808080; + color:#fff !important; + text-decoration:none; + padding:0 0.2em; + margin:0.1em 0.2em; + border:none !important; +} + +.dokuwiki div.plugin_translation ul li a:hover img { + opacity:1.0; + height:15px; +} + +body { + margin:0; + padding:0; + background-image: url(../img/dark-bg.jpg); + color:white; + font-size:12px; + font-family:Verdana, Helvetica, "Lucida Grande", Lucida, Arial, sans-serif; + font-family:sans-serif; + font-size:99, 96%; + font-size-adjust:none; + font-style:normal; + font-variant:normal; + font-weight:normal; + line-height:normal; +} +hr { + border-width:0; + border-bottom:1px #aaa dotted; +} +img { + border:none; +} +form { + margin:0px; + padding:0px; + border:none; + display:inline; + background:transparent; +} +ul li { + margin:5px; +} +textarea { + font-family:monospace; +} +table { + margin:0.5em 0; + border-collapse:collapse; +} +td { + padding:0.25em; + border:1pt solid #ADB9CC; +} +a { + color:#3465a4; + text-decoration:none; +} +a:hover { + text-decoration:underline; +} + +option { + border:0 none #fff; +} +strong.highlight { + background-color:#fc9; + padding:1pt; +} +#pagebottom { + clear:both; +} +hr { + height:1px; + color:#c0c0c0; + background-color:#c0c0c0; + border:none; + margin:.2em 0 .2em 0; +} + +.invisible { + margin:0px; + border:0px; + padding:0px; + height:0px; + visibility:hidden; +} +.left { + float:left !important; +} +.right { + float:right !important; +} +.center { + text-align:center; +} +div#body-wrapper { + padding:40px 40px 10px 40px; + font-size:127%; +} +div#content { + margin-top:-20px; + padding:0; + font-size:14px; + color:white; + line-height:1.5em; +} +h1, h2, h3, h4, h5, h6 { + background:transparent none repeat scroll 0 0; + border-bottom:1px solid #aaa; + color:white; + font-weight:normal; + margin:0; + padding:0; + padding-bottom:0.17em; + padding-top:0.5em; +} +h1 { + font-size:188%; + line-height:1.2em; + margin-bottom:0.1em; + padding-bottom:0; +} +h2 { + font-size:150%; +} +h3, h4, h5, h6 { + border-bottom:none; + font-weight:bold; +} +h3 { + font-size:132%; +} +h4 { + font-size:116%; +} +h5 { + font-size:100%; +} +h6 { + font-size:80%; +} +ul#page-actions, ul#page-actions-more { + float:right; + margin:10px 10px 0 10px; + padding:6px; + color:white; + background-color:#202020; + list-style-type:none; + white-space: nowrap; + border-radius:5px; + -moz-border-radius:5px; + border:1px solid grey; +} +ul#user-actions { + padding:5px; + margin:0; + display:inline; + color:white; + background-color:#202020; + list-style-type:none; + -moz-border-radius:3px; + border-radius:3px; +} +ul#page-actions li, ul#user-actions li, ul#page-actions-more li { + display:inline; +} +ul#page-actions a, ul#user-actions a, ul#page-actions-more a { + text-decoration:none; + color:white; + display:inline; + margin:0 3px; + padding:2px 0px 2px 18px; +} +ul#page-actions a:hover, ul#page-actions a:focus, ul#user-actions a:hover, ul#user-actions a:focus { + /*text-decoration:underline;*/ +} +/***************************/ +ul#page-actions2 { + float:left; + margin:10px 10px 0 10px; + padding:6px; + color:white; + background-color:#202020; + list-style-type:none; + border-radius:5px; + -moz-border-radius:5px; + border:1px solid grey; +} +ul#user-actions2 { + padding:5px; + margin:0; + display:inline; + color:white; + background-color:#202020; + list-style-type:none; + border-radius:3px; + -moz-border-radius:3px; +} +ul#page-actions2 li, ul#user-actions2 li { + display:inline; +} +ul#page-actions2 a, ul#user-actions2 a { + text-decoration:none; + color:white; + display:inline; + margin:0 3px; + padding:2px 0px 2px 18px; +} +ul#page-actions2 a:hover, ul#page-actions2 a:focus, ul#user-actions2 a:hover, ul#user-actions2 a:focus, +ul#page-actions-more a:hover, ul#page-actions-more a:focus{ + color: #4e7bb4; +} +/****************************/ +.hidden { + display:none; +} + +a.logout { + background:transparent url(../img/default/user-actions-logout.png) 0px 1px no-repeat; +} + +a.info { + background:transparent url(../img/default/user-info.png) 0px 1px no-repeat; +} + +a.admin { + background:transparent url(../img/default/user-actions-admin.png) 0px 1px no-repeat; +} +a.profile { + background:transparent url(../img/default/user-actions-profile.png) 0px 1px no-repeat; +} +a.create, a.edit { + background:transparent url(../img/default/page-tools-edit.png) 0px 1px no-repeat; +} +a.source, a.show { + background:transparent url(../img/default/page-tools-source.png) 0px 1px no-repeat; +} +a.revisions { + background:transparent url(../img/default/page-tools-revisions.png) 0px 1px no-repeat; +} +a.subscribe, a.unsubscribe { + background:transparent url(../img/default/page-tools-subscribe.png) 0px 1px no-repeat; +} +a.backlink { + background:transparent url(../img/default/page-tools-backlinks.png) 0px 1px no-repeat; +} +a.play { + background:transparent url(../img/default/control_play.png) 0px 1px no-repeat; +} +.time { + background:transparent url(../img/default/status_None.png) 0px 1px no-repeat; + padding: 2px 0px 2px 18px; + margin: 0px 3px; +} +.reconnect { + background:transparent url(../img/default/reconnect.png) 0px 1px no-repeat; + padding: 2px 0px 2px 18px; + margin: 0px 3px; +} +a.play:hover { + background:transparent url(../img/default/control_play_blue.png) 0px 1px no-repeat; +} +a.cancel { + background:transparent url(../img/default/control_cancel.png) 0px 1px no-repeat; +} +a.cancel:hover { + background:transparent url(../img/default/control_cancel_blue.png) 0px 1px no-repeat; +} +a.pause { + background:transparent url(../img/default/control_pause.png) 0px 1px no-repeat; +} +a.pause:hover { + background:transparent url(../img/default/control_pause_blue.png) 0px 1px no-repeat; + font-weight: bold; +} +a.stop { + background:transparent url(../img/default/control_stop.png) 0px 1px no-repeat; +} +a.stop:hover { + background:transparent url(../img/default/control_stop_blue.png) 0px 1px no-repeat; +} +a.add { + background:transparent url(../img/default/control_add.png) 0px 1px no-repeat; +} +a.add:hover { + background:transparent url(../img/default/control_add_blue.png) 0px 1px no-repeat; +} +a.cog { + background:transparent url(../img/default/cog.png) 0px 1px no-repeat; +} +#head-panel { + background:#525252 url(../img/default/head_bg1.png) bottom left repeat-x; +} +#head-panel h1 { + display:none; + margin:0; + text-decoration:none; + padding-top:0.8em; + padding-left:3.3em; + font-size:2.6em; + color:#eeeeec; +} +#head-panel #head-logo { + float:left; + margin:5px 0 -15px 5px; + padding:0; + overflow:visible; +} +#head-menu { + background:transparent url(../img/default/tabs-border-bottom.png) 0 100% repeat-x; + width:100%; + float:left; + margin:0; + padding:0; + padding-top:0.8em; +} +#head-menu ul { + list-style:none; + margin:0 1em 0 2em; +} +#head-menu ul li { + float:left; + margin:0; + margin-left:0.3em; + font-size:14px; + margin-bottom:4px; +} +#head-menu ul li.selected, #head-menu ul li:hover { + margin-bottom:0px; +} +#head-menu ul li a img { + height:22px; + width:22px; + vertical-align:middle; +} +#head-menu ul li a, #head-menu ul li a:link { + float:left; + text-decoration:none; + color:white; + background: url(../img/dark-bg.jpg) 0 100% repeat-x; + padding:3px 7px 3px 7px; + border:2px solid #ccc; + border-bottom:0px solid transparent; + padding-bottom:3px; + -moz-border-radius:5px; + border-radius:5px; +} +#head-menu ul li a:hover, #head-menu ul li a:focus { + color:#3465a4; + background-image: url(../img/dark-bg.jpg); + padding-bottom:7px; + border-bottom:0px none transparent; + outline:none; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + -moz-border-radius-bottomright:0px; + -moz-border-radius-bottomleft:0px; +} +#head-menu ul li a:focus { + margin-bottom:-4px; +} +#head-menu ul li.selected a { + color:white; + background-image: url(../img/dark-bg.jpg); + padding-bottom:7px; + border-bottom:0px none transparent; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + -moz-border-radius-bottomright:0px; + -moz-border-radius-bottomleft:0px; +} +#head-menu ul li.selected a:hover, #head-menu ul li.selected a:focus { + color:#3465a4; +} +div#head-search-and-login { + float:right; + margin:0 1em 0 0; + background-color:#222; + padding:7px 7px 5px 5px; + color:white; + white-space: nowrap; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-bottomright:6px; + -moz-border-radius-bottomleft:6px; + border-right:1px solid grey; + border-left:1px solid grey; + border-bottom:1px solid grey; +} +div#head-search-and-login form { + display:inline; + padding:0 3px; +} +div#head-search-and-login form input { + border:2px solid #888; + background:#eee; + font-size:14px; + padding:2px; + border-radius:3px; + -moz-border-radius:3px; +} +div#head-search-and-login form input:focus { + background:#fff; +} +#head-search { + font-size:14px; +} +#head-username, #head-password { + width:80px; + font-size:14px; +} +#pageinfo { + clear:both; + color:#888; + padding:0.6em 0; + margin:0; +} +#foot { + font-style:normal; + color:#888; + text-align:center; +} +#foot a { + color:#aaf; +} +#foot img { + vertical-align:middle; +} +div.toc { + border:1px dotted #888; + background:#f0f0f0; + margin:1em 0 1em 1em; + float:right; + font-size:95%; +} +div.toc .tocheader { + font-weight:bold; + margin:0.5em 1em; +} +div.toc ol { + margin:1em 0.5em 1em 1em; + padding:0; +} +div.toc ol li { + margin:0; + padding:0; + margin-left:1em; +} +div.toc ol ol { + margin:0.5em 0.5em 0.5em 1em; + padding:0; +} +div.recentchanges table { + clear:both; +} +div#editor-help { + font-size:90%; + border:1px dotted #888; + padding:0ex 1ex 1ex 1ex; + background:#f7f6f2; +} +div#preview { + margin-top:1em; +} +label.block { + display:block; + text-align:right; + font-weight:bold; +} +label.simple { + display:block; + text-align:left; + font-weight:normal; +} +label.block input.edit { + width:50%; +} +/*fieldset { + width:300px; + text-align:center; + padding:0.5em; + margin:auto; +} +*/ +div.editor { + margin:0 0 0 0; +} +table { + margin:0.5em 0; + border-collapse:collapse; +} +td { + padding:0.25em; + border:1pt solid #ADB9CC; +} +td p { + margin:0; + padding:0; +} +.u { + text-decoration:underline; +} +.footnotes ul { + padding:0 2em; + margin:0 0 1em; +} +.footnotes li { + list-style:none; +} +.userpref table, .userpref td { + border:none; +} +#message { + clear:both; + padding:5px 10px; + background-color:#eee; + border-bottom:2px solid #ccc; +} +#message p { + margin:5px 0; + padding:0; + font-weight:bold; +} +#message div.buttons { + font-weight:normal; +} +.diff { + width:99%; +} +.diff-title { + background-color:#C0C0C0; +} +.searchresult dd span { + font-weight:bold; +} +.boxtext { + font-family:tahoma, arial, sans-serif; + font-size:11px; + color:#000; + float:none; + padding:3px 0 0 10px; +} +.statusbutton { + width:32px; + height:32px; + float:left; + margin-left:-32px; + margin-right:5px; + opacity:0; + cursor:pointer +} +.dlsize { + float:left; + padding-right: 8px; +} +.dlspeed { + float:left; + padding-right: 8px; +} +.package { + margin-bottom: 10px; +} +.packagename { + font-weight: bold; +} + +.child { + margin-left: 20px; +} +.child_status { + margin-right: 10px; +} +.child_secrow { + font-size: 10px; +} + +.header, .header th { + text-align: left; + font-weight: normal; + background-color:#202020; + border-top:1px solid grey; + border-bottom:1px solid grey; + -moz-border-radius:5px; + border-radius:5px; +} +.progress_bar { + background: #0C0; + height: 5px; + +} + +.queue { + border: none +} + +.queue tr td { + border: none +} + +.header, .header th{ + text-align: left; + font-weight: normal; +} + + +.clearer +{ + clear: both; + height: 1px; +} + +.left +{ + float: left; +} + +.right +{ + float: right; +} + + +.setfield +{ + display: table-cell; +} + +ul.tabs li a +{ + padding: 5px 16px 4px 15px; + border: none; + font-weight: bold; + + border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + +} + + +#tabs span +{ + display: none; +} + +#tabs span.selected +{ + display: inline; +} + +#tabsback +{ + background-color: #525252; + margin: 2px 0 0; + padding: 6px 4px 1px 4px; + + border-top-right-radius: 30px; + border-top-left-radius: 3px; + -moz-border-radius-topright: 30px; + -moz-border-radius-topleft: 3px; +} +ul.tabs +{ + list-style-type: none; + margin:0; + padding: 0 40px 0 0; +} + +ul.tabs li +{ + display: inline; + margin-left: 8px; +} + +ul.tabs li a +{ + color: white; + background-color: #202020; + border: 1px solid grey; + border-bottom:none; + margin: 0; + text-decoration: none; + + outline: 0; + + padding: 5px 16px 4px 15px; + font-weight: bold; + + border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + +} + +ul.tabs li a.selected, ul.tabs li a:hover +{ + color: #3465a4; + background-color: white; + + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomright: 0; + -moz-border-radius-bottomleft: 0; +} + +ul.tabs li a:hover +{ + background-color: #202020; +} + +ul.tabs li a.selected +{ + font-weight: bold; + background-color: #525252; + padding-bottom: 5px; + color: white; +} + + +#tabs-body { + position: relative; + overflow: hidden; +} + + +span.tabContent +{ + border: 2px solid #525252; + margin: 0; + padding: 0; + padding-bottom: 10px; +} + +#tabs-body > span { + display: none; +} + +#tabs-body > span.active { + display: block; +} + +.hide +{ + display: none; +} + +.settable +{ + color:white; + margin: 20px; + border: none; +} +.settable td +{ + border: none; + margin: 0; + padding: 5px; +} + +.settable th{ + padding-bottom: 8px; +} + +.settable.wide td , .settable.wide th { + padding-left: 15px; + padding-right: 15px; +} + +.settable input { +background-color:#202020; +color:white; +} +.settable select { +background-color:#202020; +color:white; +} + +ul.nav { + margin: -30px 0 0; + padding: 0; + list-style: none; + position: absolute; +} + + +ul.nav li { + position: relative; + float: left; + padding: 5px; +} + +ul.nav > li a { + background: #202020; + -moz-border-radius: 4px 4px 4px 4px; + border: 1px solid grey; + border-bottom: medium none; + color: white; +} + +ul.nav ul { + position: absolute; + top: 26px; + left: 10px; + margin: 0; + padding: 0; + list-style: none; + border: 1px solid #AAA; + background: #202020; + -webkit-box-shadow: 1px 1px 5px #AAA; + -moz-box-shadow: 1px 1px 5px #AAA; + box-shadow: 1px 1px 5px #AAA; + cursor: pointer; +} + +ul.nav .open { + display: block; +} + +ul.nav .close { + display: none; +} + +ul.nav ul li { + float: none; + padding: 0; +} + +ul.nav ul li a { + width: 130px; + background: #f1f1f1; + padding: 3px; + display: block; + font-weight: normal; +} + +ul.nav ul li a:hover { + background: #CDCDCD; +} + +ul.nav ul ul { + left: 137px; + top: 0; +} + +.purr-wrapper{ + margin:10px; +} + +/*Purr alert styles*/ + +.purr-alert{ + margin-bottom:10px; + padding:10px; + background:#000; + font-size:13px; + font-weight:bold; + color:#FFF; + -moz-border-radius:5px; + -webkit-border-radius:5px; + /*-moz-box-shadow: 0 0 10px rgba(255,255,0,.25);*/ + width:300px; +} +.purr-alert.error{ + color:#F55; + padding-left:30px; + background:url(../img/default/error.png) no-repeat #000 7px 10px; + width:280px; +} +.purr-alert.success{ + color:#5F5; + padding-left:30px; + background:url(../img/default/success.png) no-repeat #000 7px 10px; + width:280px; +} +.purr-alert.notice{ + color:#99F; + padding-left:30px; + background:url(../img/default/notice.png) no-repeat #000 7px 10px; + width:280px; +} + +table.system { + border: none; + margin-left: 10px; +} + +table.system td { + border: none +} + +table.system tr > td:first-child { + font-weight: bold; + padding-right: 10px; +} + +#foot { +color:white; +} + +#login_table { +margin-left:auto; +margin-right:auto; +} + +#login_table td { +padding:5px; +border:1px solid grey; +} + +#login_table input[type=text], #login_table input[type=password] { +width:120px; +background-color:transparent; +-moz-opacity: 0.10; +color:white; +border: 1px solid grey; +-moz-border-radius: 2px; +-webkit-border-radius: 2px; +border-radius: 18px; +padding-left:5px; +padding-right:5px; +} + +#login_table input[type=text]:focus, #login_table input[type=password]:focus { +border:1px solid #3465a4; +} + +#login_table input[type=submit] { +background-color:transparent; +color:white; +border: 1px solid grey; +-moz-border-radius: 2px; +-webkit-border-radius: 2px; +border-radius: 18px; +} + +#login_table input[type=submit]:hover { +border:1px solid #3465a4; +}
\ No newline at end of file diff --git a/module/webui/themes/dark/css/log.css b/module/webui/themes/dark/css/log.css new file mode 100644 index 000000000..41aa19616 --- /dev/null +++ b/module/webui/themes/dark/css/log.css @@ -0,0 +1,75 @@ + +html, body, #content +{ + height: 100%; +} +#body-wrapper +{ + height: 70%; +} +.logdiv +{ + height: 90%; + width: 100%; + overflow: auto; + border: 2px solid #CCC; + outline: 1px solid #666; + background-color: #FFE; + margin-right: auto; + margin-left: auto; + background-color:#202020; + color:white; +} +.logform +{ + display: table; + margin: 0 auto 0 auto; + padding-top: 5px; + color: white; +} +.logtable +{ + + margin: 0px; +} +.logtable td +{ + border: none; + white-space: nowrap; + + + font-family: monospace; + font-size: 16px; + margin: 0px; + padding: 0px 10px 0px 10px; + line-height: 110%; +} +td.logline +{ + background-color: #202020; + text-align:right; + padding: 0px 5px 0px 5px; +} +td.loglevel +{ + text-align:right; +} +.logperpage +{ + float: right; + padding-bottom: 8px; +} +.logpaginator +{ + float: left; + padding-top: 5px; +} +.logpaginator a +{ + padding: 0px 8px 0px 8px; +} +.logwarn +{ + text-align: center; + color: red; +}
\ No newline at end of file diff --git a/module/web/media/default/css/pathchooser.css b/module/webui/themes/dark/css/pathchooser.css index 894cc335e..894cc335e 100644 --- a/module/web/media/default/css/pathchooser.css +++ b/module/webui/themes/dark/css/pathchooser.css diff --git a/module/webui/themes/dark/css/window.css b/module/webui/themes/dark/css/window.css new file mode 100644 index 000000000..11ba84b39 --- /dev/null +++ b/module/webui/themes/dark/css/window.css @@ -0,0 +1,92 @@ +/* ----------- stylized ----------- */ +.window_table td { +border:none; +text-align:left; +} +#add_box { +background-image: url(../img/dark-bg.jpg); +color:white; +} +#pack_box { +background-image: url(../img/dark-bg.jpg); +color:white; +} +.window_box h1{ + font-size:14px; + font-weight:bold; + margin-bottom:8px; +} +.window_box p{ + font-size:11px; + color:white; + margin-bottom:20px; + border-bottom:solid 1px #b7ddf2; + padding-bottom:10px; +} +.window_box label{ /*Linke Seite*/ + display:block; + font-weight:bold; + text-align:right; + width:240px; + float:left; + color:white; +} +.window_box .small{ + color:grey; + display:block; + font-size:11px; + font-weight:normal; + text-align:right; + width:240px; +} +.window_box select, .window_box input{ + float:left; + font-size:12px; + padding:4px 2px; + border:solid 1px #aacfe4; + width:300px; + margin:2px 0 20px 10px; + background-color:#202020; + color:white; +} +.window_box .cont{ + float:left; + font-size:12px; + padding: 0px 10px 15px 0px; + width:300px; + margin:0px 0px 0px 10px; + color:white; +} +.window_box .cont input{ + float: none; + margin: 0px 15px 0px 1px; + color:white; +} +.window_box textarea{ + float:left; + font-size:12px; + padding:4px 2px; + border:solid 1px #aacfe4; + width:300px; + margin:2px 0 20px 10px; + background-color:#202020; + color:white; +} +.window_box button, .styled_button{ + clear:both; + margin-left:150px; + width:125px; + height:31px; + background:#666666 url(../img/button.png) no-repeat; + text-align:center; + line-height:31px; + color:#FFFFFF; + font-size:11px; + font-weight:bold; + border: 0px; +} + +.styled_button { + margin-left: 15px; + cursor: pointer; +} diff --git a/module/web/media/img/dialog-close.png b/module/webui/themes/dark/img/MooDialog/dialog-close.png Binary files differindex 81ebb88b2..81ebb88b2 100644 --- a/module/web/media/img/dialog-close.png +++ b/module/webui/themes/dark/img/MooDialog/dialog-close.png diff --git a/module/webui/themes/dark/img/MooDialog/dialog-error.png b/module/webui/themes/dark/img/MooDialog/dialog-error.png Binary files differnew file mode 100644 index 000000000..d70328403 --- /dev/null +++ b/module/webui/themes/dark/img/MooDialog/dialog-error.png diff --git a/module/web/media/img/dialog-question.png b/module/webui/themes/dark/img/MooDialog/dialog-question.png Binary files differindex b0af3db5b..b0af3db5b 100644 --- a/module/web/media/img/dialog-question.png +++ b/module/webui/themes/dark/img/MooDialog/dialog-question.png diff --git a/module/webui/themes/dark/img/MooDialog/dialog-warning.png b/module/webui/themes/dark/img/MooDialog/dialog-warning.png Binary files differnew file mode 100644 index 000000000..aad64d4be --- /dev/null +++ b/module/webui/themes/dark/img/MooDialog/dialog-warning.png diff --git a/module/webui/themes/dark/img/button.png b/module/webui/themes/dark/img/button.png Binary files differnew file mode 100644 index 000000000..bb408a7d6 --- /dev/null +++ b/module/webui/themes/dark/img/button.png diff --git a/module/webui/themes/dark/img/dark-bg.jpg b/module/webui/themes/dark/img/dark-bg.jpg Binary files differnew file mode 100644 index 000000000..637fa6b93 --- /dev/null +++ b/module/webui/themes/dark/img/dark-bg.jpg diff --git a/module/web/media/default/img/add_folder.png b/module/webui/themes/dark/img/default/add_folder.png Binary files differindex 8acbc411b..8acbc411b 100644 --- a/module/web/media/default/img/add_folder.png +++ b/module/webui/themes/dark/img/default/add_folder.png diff --git a/module/web/media/default/img/ajax-loader.gif b/module/webui/themes/dark/img/default/ajax-loader.gif Binary files differindex 2fd8e0737..2fd8e0737 100644 --- a/module/web/media/default/img/ajax-loader.gif +++ b/module/webui/themes/dark/img/default/ajax-loader.gif diff --git a/module/web/media/default/img/arrow_refresh.png b/module/webui/themes/dark/img/default/arrow_refresh.png Binary files differindex 0de26566d..0de26566d 100644 --- a/module/web/media/default/img/arrow_refresh.png +++ b/module/webui/themes/dark/img/default/arrow_refresh.png diff --git a/module/web/media/default/img/arrow_right.png b/module/webui/themes/dark/img/default/arrow_right.png Binary files differindex b1a181923..b1a181923 100644 --- a/module/web/media/default/img/arrow_right.png +++ b/module/webui/themes/dark/img/default/arrow_right.png diff --git a/module/web/media/default/img/big_button.gif b/module/webui/themes/dark/img/default/big_button.gif Binary files differindex 7680490ea..7680490ea 100644 --- a/module/web/media/default/img/big_button.gif +++ b/module/webui/themes/dark/img/default/big_button.gif diff --git a/module/web/media/default/img/big_button_over.gif b/module/webui/themes/dark/img/default/big_button_over.gif Binary files differindex 2e3ee10d2..2e3ee10d2 100644 --- a/module/web/media/default/img/big_button_over.gif +++ b/module/webui/themes/dark/img/default/big_button_over.gif diff --git a/module/web/media/default/img/body.png b/module/webui/themes/dark/img/default/body.png Binary files differindex 7ff1043e0..7ff1043e0 100644 --- a/module/web/media/default/img/body.png +++ b/module/webui/themes/dark/img/default/body.png diff --git a/module/web/media/default/img/closebtn.gif b/module/webui/themes/dark/img/default/closebtn.gif Binary files differindex 3e27e6030..3e27e6030 100644 --- a/module/web/media/default/img/closebtn.gif +++ b/module/webui/themes/dark/img/default/closebtn.gif diff --git a/module/web/media/default/img/cog.png b/module/webui/themes/dark/img/default/cog.png Binary files differindex 67de2c6cc..67de2c6cc 100644 --- a/module/web/media/default/img/cog.png +++ b/module/webui/themes/dark/img/default/cog.png diff --git a/module/web/media/default/img/control_add.png b/module/webui/themes/dark/img/default/control_add.png Binary files differindex d39886893..d39886893 100644 --- a/module/web/media/default/img/control_add.png +++ b/module/webui/themes/dark/img/default/control_add.png diff --git a/module/web/media/default/img/control_add_blue.png b/module/webui/themes/dark/img/default/control_add_blue.png Binary files differindex d11b7f41d..d11b7f41d 100644 --- a/module/web/media/default/img/control_add_blue.png +++ b/module/webui/themes/dark/img/default/control_add_blue.png diff --git a/module/web/media/default/img/control_cancel.png b/module/webui/themes/dark/img/default/control_cancel.png Binary files differindex 7b9bc3fba..7b9bc3fba 100644 --- a/module/web/media/default/img/control_cancel.png +++ b/module/webui/themes/dark/img/default/control_cancel.png diff --git a/module/web/media/default/img/control_cancel_blue.png b/module/webui/themes/dark/img/default/control_cancel_blue.png Binary files differindex 0c5c96ce3..0c5c96ce3 100644 --- a/module/web/media/default/img/control_cancel_blue.png +++ b/module/webui/themes/dark/img/default/control_cancel_blue.png diff --git a/module/web/media/default/img/control_pause.png b/module/webui/themes/dark/img/default/control_pause.png Binary files differindex 2d9ce9c4e..2d9ce9c4e 100644 --- a/module/web/media/default/img/control_pause.png +++ b/module/webui/themes/dark/img/default/control_pause.png diff --git a/module/web/media/default/img/control_pause_blue.png b/module/webui/themes/dark/img/default/control_pause_blue.png Binary files differindex ec61099b0..ec61099b0 100644 --- a/module/web/media/default/img/control_pause_blue.png +++ b/module/webui/themes/dark/img/default/control_pause_blue.png diff --git a/module/web/media/default/img/control_play.png b/module/webui/themes/dark/img/default/control_play.png Binary files differindex 0846555d0..0846555d0 100644 --- a/module/web/media/default/img/control_play.png +++ b/module/webui/themes/dark/img/default/control_play.png diff --git a/module/web/media/default/img/control_play_blue.png b/module/webui/themes/dark/img/default/control_play_blue.png Binary files differindex f8c8ec683..f8c8ec683 100644 --- a/module/web/media/default/img/control_play_blue.png +++ b/module/webui/themes/dark/img/default/control_play_blue.png diff --git a/module/web/media/default/img/control_stop.png b/module/webui/themes/dark/img/default/control_stop.png Binary files differindex 893bb60e5..893bb60e5 100644 --- a/module/web/media/default/img/control_stop.png +++ b/module/webui/themes/dark/img/default/control_stop.png diff --git a/module/web/media/default/img/control_stop_blue.png b/module/webui/themes/dark/img/default/control_stop_blue.png Binary files differindex e6f75d232..e6f75d232 100644 --- a/module/web/media/default/img/control_stop_blue.png +++ b/module/webui/themes/dark/img/default/control_stop_blue.png diff --git a/module/web/media/default/img/delete.png b/module/webui/themes/dark/img/default/delete.png Binary files differindex 08f249365..08f249365 100644 --- a/module/web/media/default/img/delete.png +++ b/module/webui/themes/dark/img/default/delete.png diff --git a/module/web/media/default/img/drag_corner.gif b/module/webui/themes/dark/img/default/drag_corner.gif Binary files differindex befb1adf1..befb1adf1 100644 --- a/module/web/media/default/img/drag_corner.gif +++ b/module/webui/themes/dark/img/default/drag_corner.gif diff --git a/module/web/media/default/img/error.png b/module/webui/themes/dark/img/default/error.png Binary files differindex c37bd062e..c37bd062e 100644 --- a/module/web/media/default/img/error.png +++ b/module/webui/themes/dark/img/default/error.png diff --git a/module/web/media/default/img/folder.png b/module/webui/themes/dark/img/default/folder.png Binary files differindex 784e8fa48..784e8fa48 100644 --- a/module/web/media/default/img/folder.png +++ b/module/webui/themes/dark/img/default/folder.png diff --git a/module/web/media/default/img/full.png b/module/webui/themes/dark/img/default/full.png Binary files differindex fea52af76..fea52af76 100644 --- a/module/web/media/default/img/full.png +++ b/module/webui/themes/dark/img/default/full.png diff --git a/module/web/media/default/img/head-login.png b/module/webui/themes/dark/img/default/head-login.png Binary files differindex b59b7cbbf..b59b7cbbf 100644 --- a/module/web/media/default/img/head-login.png +++ b/module/webui/themes/dark/img/default/head-login.png diff --git a/module/web/media/default/img/head-menu-collector.png b/module/webui/themes/dark/img/default/head-menu-collector.png Binary files differindex 861be40bc..861be40bc 100644 --- a/module/web/media/default/img/head-menu-collector.png +++ b/module/webui/themes/dark/img/default/head-menu-collector.png diff --git a/module/web/media/default/img/head-menu-config.png b/module/webui/themes/dark/img/default/head-menu-config.png Binary files differindex bbf43d4f3..bbf43d4f3 100644 --- a/module/web/media/default/img/head-menu-config.png +++ b/module/webui/themes/dark/img/default/head-menu-config.png diff --git a/module/web/media/default/img/head-menu-development.png b/module/webui/themes/dark/img/default/head-menu-development.png Binary files differindex fad150fe1..fad150fe1 100644 --- a/module/web/media/default/img/head-menu-development.png +++ b/module/webui/themes/dark/img/default/head-menu-development.png diff --git a/module/web/media/default/img/head-menu-download.png b/module/webui/themes/dark/img/default/head-menu-download.png Binary files differindex 98c5da9db..98c5da9db 100644 --- a/module/web/media/default/img/head-menu-download.png +++ b/module/webui/themes/dark/img/default/head-menu-download.png diff --git a/module/web/media/default/img/head-menu-home.png b/module/webui/themes/dark/img/default/head-menu-home.png Binary files differindex 9d62109aa..9d62109aa 100644 --- a/module/web/media/default/img/head-menu-home.png +++ b/module/webui/themes/dark/img/default/head-menu-home.png diff --git a/module/web/media/default/img/head-menu-index.png b/module/webui/themes/dark/img/default/head-menu-index.png Binary files differindex 44d631064..44d631064 100644 --- a/module/web/media/default/img/head-menu-index.png +++ b/module/webui/themes/dark/img/default/head-menu-index.png diff --git a/module/web/media/default/img/head-menu-news.png b/module/webui/themes/dark/img/default/head-menu-news.png Binary files differindex 43950ebc9..43950ebc9 100644 --- a/module/web/media/default/img/head-menu-news.png +++ b/module/webui/themes/dark/img/default/head-menu-news.png diff --git a/module/web/media/default/img/head-menu-queue.png b/module/webui/themes/dark/img/default/head-menu-queue.png Binary files differindex be98793ce..be98793ce 100644 --- a/module/web/media/default/img/head-menu-queue.png +++ b/module/webui/themes/dark/img/default/head-menu-queue.png diff --git a/module/web/media/default/img/head-menu-recent.png b/module/webui/themes/dark/img/default/head-menu-recent.png Binary files differindex fc9b0497f..fc9b0497f 100644 --- a/module/web/media/default/img/head-menu-recent.png +++ b/module/webui/themes/dark/img/default/head-menu-recent.png diff --git a/module/web/media/default/img/head-menu-wiki.png b/module/webui/themes/dark/img/default/head-menu-wiki.png Binary files differindex 07cf0102d..07cf0102d 100644 --- a/module/web/media/default/img/head-menu-wiki.png +++ b/module/webui/themes/dark/img/default/head-menu-wiki.png diff --git a/module/web/media/default/img/head-search-noshadow.png b/module/webui/themes/dark/img/default/head-search-noshadow.png Binary files differindex aafdae015..aafdae015 100644 --- a/module/web/media/default/img/head-search-noshadow.png +++ b/module/webui/themes/dark/img/default/head-search-noshadow.png diff --git a/module/web/media/default/img/head_bg1.png b/module/webui/themes/dark/img/default/head_bg1.png Binary files differindex f2848c3cc..f2848c3cc 100644 --- a/module/web/media/default/img/head_bg1.png +++ b/module/webui/themes/dark/img/default/head_bg1.png diff --git a/module/web/media/default/img/images.png b/module/webui/themes/dark/img/default/images.png Binary files differindex 184860d1e..184860d1e 100644 --- a/module/web/media/default/img/images.png +++ b/module/webui/themes/dark/img/default/images.png diff --git a/module/web/media/default/img/notice.png b/module/webui/themes/dark/img/default/notice.png Binary files differindex 12cd1aef9..12cd1aef9 100644 --- a/module/web/media/default/img/notice.png +++ b/module/webui/themes/dark/img/default/notice.png diff --git a/module/web/media/default/img/package_go.png b/module/webui/themes/dark/img/default/package_go.png Binary files differindex aace63ad6..aace63ad6 100644 --- a/module/web/media/default/img/package_go.png +++ b/module/webui/themes/dark/img/default/package_go.png diff --git a/module/web/media/default/img/page-tools-backlinks.png b/module/webui/themes/dark/img/default/page-tools-backlinks.png Binary files differindex 3eb6a9ce3..3eb6a9ce3 100644 --- a/module/web/media/default/img/page-tools-backlinks.png +++ b/module/webui/themes/dark/img/default/page-tools-backlinks.png diff --git a/module/web/media/default/img/page-tools-edit.png b/module/webui/themes/dark/img/default/page-tools-edit.png Binary files differindex 188e1c12b..188e1c12b 100644 --- a/module/web/media/default/img/page-tools-edit.png +++ b/module/webui/themes/dark/img/default/page-tools-edit.png diff --git a/module/web/media/default/img/page-tools-revisions.png b/module/webui/themes/dark/img/default/page-tools-revisions.png Binary files differindex 5c3b8587f..5c3b8587f 100644 --- a/module/web/media/default/img/page-tools-revisions.png +++ b/module/webui/themes/dark/img/default/page-tools-revisions.png diff --git a/module/web/media/default/img/parseUri.png b/module/webui/themes/dark/img/default/parseUri.png Binary files differindex 937bded9d..937bded9d 100644 --- a/module/web/media/default/img/parseUri.png +++ b/module/webui/themes/dark/img/default/parseUri.png diff --git a/module/web/media/default/img/pencil.png b/module/webui/themes/dark/img/default/pencil.png Binary files differindex 0bfecd50e..0bfecd50e 100644 --- a/module/web/media/default/img/pencil.png +++ b/module/webui/themes/dark/img/default/pencil.png diff --git a/module/web/media/default/img/reconnect.png b/module/webui/themes/dark/img/default/reconnect.png Binary files differindex 49b269145..49b269145 100644 --- a/module/web/media/default/img/reconnect.png +++ b/module/webui/themes/dark/img/default/reconnect.png diff --git a/module/web/media/default/img/status_None.png b/module/webui/themes/dark/img/default/status_None.png Binary files differindex 293b13f77..293b13f77 100644 --- a/module/web/media/default/img/status_None.png +++ b/module/webui/themes/dark/img/default/status_None.png diff --git a/module/web/media/default/img/status_downloading.png b/module/webui/themes/dark/img/default/status_downloading.png Binary files differindex fb4ebc850..fb4ebc850 100644 --- a/module/web/media/default/img/status_downloading.png +++ b/module/webui/themes/dark/img/default/status_downloading.png diff --git a/module/web/media/default/img/status_failed.png b/module/webui/themes/dark/img/default/status_failed.png Binary files differindex c37bd062e..c37bd062e 100644 --- a/module/web/media/default/img/status_failed.png +++ b/module/webui/themes/dark/img/default/status_failed.png diff --git a/module/web/media/default/img/status_finished.png b/module/webui/themes/dark/img/default/status_finished.png Binary files differindex 89c8129a4..89c8129a4 100644 --- a/module/web/media/default/img/status_finished.png +++ b/module/webui/themes/dark/img/default/status_finished.png diff --git a/module/web/media/default/img/status_offline.png b/module/webui/themes/dark/img/default/status_offline.png Binary files differindex 0cfd58596..0cfd58596 100644 --- a/module/web/media/default/img/status_offline.png +++ b/module/webui/themes/dark/img/default/status_offline.png diff --git a/module/web/media/default/img/status_proc.png b/module/webui/themes/dark/img/default/status_proc.png Binary files differindex 67de2c6cc..67de2c6cc 100644 --- a/module/web/media/default/img/status_proc.png +++ b/module/webui/themes/dark/img/default/status_proc.png diff --git a/module/web/media/default/img/status_queue.png b/module/webui/themes/dark/img/default/status_queue.png Binary files differindex 293b13f77..293b13f77 100644 --- a/module/web/media/default/img/status_queue.png +++ b/module/webui/themes/dark/img/default/status_queue.png diff --git a/module/web/media/default/img/status_waiting.png b/module/webui/themes/dark/img/default/status_waiting.png Binary files differindex 2842cc338..2842cc338 100644 --- a/module/web/media/default/img/status_waiting.png +++ b/module/webui/themes/dark/img/default/status_waiting.png diff --git a/module/web/media/default/img/success.png b/module/webui/themes/dark/img/default/success.png Binary files differindex 89c8129a4..89c8129a4 100644 --- a/module/web/media/default/img/success.png +++ b/module/webui/themes/dark/img/default/success.png diff --git a/module/web/media/default/img/tabs-border-bottom.png b/module/webui/themes/dark/img/default/tabs-border-bottom.png Binary files differindex 02440f428..02440f428 100644 --- a/module/web/media/default/img/tabs-border-bottom.png +++ b/module/webui/themes/dark/img/default/tabs-border-bottom.png diff --git a/module/web/media/default/img/user-actions-logout.png b/module/webui/themes/dark/img/default/user-actions-logout.png Binary files differindex 0010931e2..0010931e2 100644 --- a/module/web/media/default/img/user-actions-logout.png +++ b/module/webui/themes/dark/img/default/user-actions-logout.png diff --git a/module/web/media/default/img/user-actions-profile.png b/module/webui/themes/dark/img/default/user-actions-profile.png Binary files differindex 46573fff6..46573fff6 100644 --- a/module/web/media/default/img/user-actions-profile.png +++ b/module/webui/themes/dark/img/default/user-actions-profile.png diff --git a/module/web/media/default/img/user-info.png b/module/webui/themes/dark/img/default/user-info.png Binary files differindex 6e643100f..6e643100f 100644 --- a/module/web/media/default/img/user-info.png +++ b/module/webui/themes/dark/img/default/user-info.png diff --git a/module/webui/themes/dark/img/pyload-logo.png b/module/webui/themes/dark/img/pyload-logo.png Binary files differnew file mode 100644 index 000000000..e878afee5 --- /dev/null +++ b/module/webui/themes/dark/img/pyload-logo.png diff --git a/module/webui/themes/dark/img/tab-background.png b/module/webui/themes/dark/img/tab-background.png Binary files differnew file mode 100644 index 000000000..ee96b8407 --- /dev/null +++ b/module/webui/themes/dark/img/tab-background.png diff --git a/module/webui/themes/dark/js/render/admin.coffee b/module/webui/themes/dark/js/render/admin.coffee new file mode 100644 index 000000000..5afbcbb66 --- /dev/null +++ b/module/webui/themes/dark/js/render/admin.coffee @@ -0,0 +1,58 @@ +root = this + +window.addEvent "domready", -> + + root.passwordDialog = new MooDialog {destroyOnHide: false} + root.passwordDialog.setContent $ 'password_box' + + $("login_password_reset").addEvent "click", (e) -> root.passwordDialog.close() + $("login_password_button").addEvent "click", (e) -> + + newpw = $("login_new_password").get("value") + newpw2 = $("login_new_password2").get("value") + + if newpw is newpw2 + form = $("password_form") + form.set "send", { + onSuccess: (data) -> + root.notify.alert "Success", { + 'className': 'success' + } + onFailure: (data) -> + root.notify.alert "Error", { + 'className': 'error' + } + } + + form.send() + + root.passwordDialog.close() + else + alert '{{_("Passwords did not match.")}}' + + e.stop() + + for item in $$(".change_password") + id = item.get("id") + user = id.split("|")[1] + $("user_login").set("value", user) + item.addEvent "click", (e) -> root.passwordDialog.open() + + $('quit-pyload').addEvent "click", (e) -> + new MooDialog.Confirm "{{_('You are really sure you want to quit pyLoad?')}}", -> + new Request.JSON({ + url: '/api/kill' + method: 'get' + }).send() + , -> + e.stop() + + $('restart-pyload').addEvent "click", (e) -> + new MooDialog.Confirm "{{_('Are you sure you want to restart pyLoad?')}}", -> + new Request.JSON({ + url: '/api/restart' + method: 'get' + onSuccess: (data) -> alert "{{_('pyLoad restarted')}}" + }).send() + , -> + e.stop() diff --git a/module/web/media/js/admin.js b/module/webui/themes/dark/js/render/admin.min.js index d34d310a0..94a5e494d 100644 --- a/module/web/media/js/admin.js +++ b/module/webui/themes/dark/js/render/admin.min.js @@ -1,3 +1,3 @@ {% autoescape true %} var root;root=this;window.addEvent("domready",function(){var f,c,b,e,a,d;root.passwordDialog=new MooDialog({destroyOnHide:false});root.passwordDialog.setContent($("password_box"));$("login_password_reset").addEvent("click",function(g){return root.passwordDialog.close()});$("login_password_button").addEvent("click",function(j){var h,i,g;i=$("login_new_password").get("value");g=$("login_new_password2").get("value");if(i===g){h=$("password_form");h.set("send",{onSuccess:function(k){return root.notify.alert("Success",{className:"success"})},onFailure:function(k){return root.notify.alert("Error",{className:"error"})}});h.send();root.passwordDialog.close()}else{alert('{{_("Passwords did not match.")}}')}return j.stop()});d=$$(".change_password");for(e=0,a=d.length;e<a;e++){c=d[e];f=c.get("id");b=f.split("|")[1];$("user_login").set("value",b);c.addEvent("click",function(g){return root.passwordDialog.open()})}$("quit-pyload").addEvent("click",function(g){new MooDialog.Confirm("{{_('You are really sure you want to quit pyLoad?')}}",function(){return new Request.JSON({url:"/api/kill",method:"get"}).send()},function(){});return g.stop()});return $("restart-pyload").addEvent("click",function(g){new MooDialog.Confirm("{{_('Are you sure you want to restart pyLoad?')}}",function(){return new Request.JSON({url:"/api/restart",method:"get",onSuccess:function(h){return alert("{{_('pyLoad restarted')}}")}}).send()},function(){});return g.stop()})}); -{% endautoescape %}
\ No newline at end of file +{% endautoescape %} diff --git a/module/webui/themes/dark/js/render/base.coffee b/module/webui/themes/dark/js/render/base.coffee new file mode 100644 index 000000000..07b8bfb6f --- /dev/null +++ b/module/webui/themes/dark/js/render/base.coffee @@ -0,0 +1,177 @@ +# External scope +root = this + +# helper functions +humanFileSize = (size) -> + filesizename = new Array("B", "KiB", "MiB", "GiB", "TiB", "PiB") + loga = Math.log(size) / Math.log(1024) + i = Math.floor(loga) + a = Math.pow(1024, i) + if size is 0 then "0 B" else (Math.round(size * 100 / a) / 100 + " " + filesizename[i]) + + +parseUri = () -> + oldString = $("add_links").value + regxp = new RegExp('(ht|f)tp(s?):\/\/[a-zA-Z0-9\-\.\/\?=_&%#]+[<| |\"|\'|\r|\n|\t]{1}', 'g') + resu = oldString.match regxp + return if resu == null + res = "" + + for part in resu + if part.indexOf(" ") != -1 + res = res + part.replace(" ", " \n") + else if part.indexOf("\t") != -1 + res = res + part.replace("\t", " \n") + else if part.indexOf("\r") != -1 + res = res + part.replace("\r", " \n") + else if part.indexOf("\"") != -1 + res = res + part.replace("\"", " \n") + else if part.indexOf("<") != -1 + res = res + part.replace("<", " \n") + else if part.indexOf("'") != -1 + res = res + part.replace("'", " \n") + else + res = res + part.replace("\n", " \n") + + $("add_links").value = res + + +Array::remove = (from, to) -> + rest = this.slice((to || from) + 1 || this.length) + this.length = from < 0 ? this.length + from : from + return [] if this.length == 0 + return this.push.apply(this, rest) + + +document.addEvent "domready", -> + + # global notification + root.notify = new Purr { + 'mode': 'top' + 'position': 'center' + } + + root.captchaBox = new MooDialog {destroyOnHide: false} + root.captchaBox.setContent $ 'cap_box' + + root.addBox = new MooDialog {destroyOnHide: false} + root.addBox.setContent $ 'add_box' + + $('add_form').onsubmit = -> + $('add_form').target = 'upload_target' + if $('add_name').value is "" and $('add_file').value is "" + alert '{{_("Please Enter a packagename.")}}' + return false + else + root.addBox.close() + return true + + $('add_reset').addEvent 'click', -> root.addBox.close() + + $('action_add').addEvent 'click', -> $("add_form").reset(); root.addBox.open() + $('action_play').addEvent 'click', -> new Request({method: 'get', url: '/api/unpauseServer'}).send() + $('action_cancel').addEvent 'click', -> new Request({method: 'get', url: '/api/stopAllDownloads'}).send() + $('action_stop').addEvent 'click', -> new Request({method: 'get', url: '/api/pauseServer'}).send() + + + # captcha events + + $('cap_info').addEvent 'click', -> + load_captcha "get", "" + root.captchaBox.open() + $('cap_reset').addEvent 'click', -> root.captchaBox.close() + $('cap_form').addEvent 'submit', (e) -> + submit_captcha() + e.stop() + + $('cap_positional').addEvent 'click', on_captcha_click + + new Request.JSON({ + url: "/json/status" + onSuccess: LoadJsonToContent + secure: false + async: true + initialDelay: 0 + delay: 4000 + limit: 3000 + }).startTimer() + + +LoadJsonToContent = (data) -> + $("speed").set 'text', humanFileSize(data.speed)+"/s" + $("aktiv").set 'text', data.active + $("aktiv_from").set 'text', data.queue + $("aktiv_total").set 'text', data.total + + if data.captcha + if $("cap_info").getStyle("display") != "inline" + $("cap_info").setStyle 'display', 'inline' + root.notify.alert '{{_("New Captcha Request")}}', { + 'className': 'notify' + } + else + $("cap_info").setStyle 'display', 'none' + + + if data.download + $("time").set 'text', ' {{_("on")}}' + $("time").setStyle 'background-color', "#8ffc25" + else + $("time").set 'text', ' {{_("off")}}' + $("time").setStyle 'background-color', "#fc6e26" + + if data.reconnect + $("reconnect").set 'text', ' {{_("on")}}' + $("reconnect").setStyle 'background-color', "#8ffc25" + else + $("reconnect").set 'text', ' {{_("off")}}' + $("reconnect").setStyle 'background-color', "#fc6e26" + + return null + + +set_captcha = (data) -> + $('cap_id').set 'value', data.id + if (data.result_type is 'textual') + $('cap_textual_img').set 'src', data.src + $('cap_title').set 'text', '{{_("Please read the text on the captcha.")}}' + $('cap_submit').setStyle 'display', 'inline' + $('cap_textual').setStyle 'display', 'block' + $('cap_positional').setStyle 'display', 'none' + + else if (data.result_type == 'positional') + $('cap_positional_img').set('src', data.src) + $('cap_title').set('text', '{{_("Please click on the right captcha position.")}}') + $('cap_submit').setStyle('display', 'none') + $('cap_textual').setStyle('display', 'none') + + +load_captcha = (method, post) -> + new Request.JSON({ + url: "/json/set_captcha" + onSuccess: (data) -> set_captcha(data) if data.captcha else clear_captcha() + secure: false + async: true + method: method + }).send(post) + + +clear_captcha = -> + $('cap_textual').setStyle 'display', 'none' + $('cap_textual_img').set 'src', '' + $('cap_positional').setStyle 'display', 'none' + $('cap_positional_img').set 'src', '' + $('cap_title').set 'text', '{{_("No Captchas to read.")}}' + + +submit_captcha = -> + load_captcha("post", "cap_id=" + $('cap_id').get('value') + "&cap_result=" + $('cap_result').get('value') ) + $('cap_result').set('value', '') + + +on_captcha_click = (e) -> + position = e.target.getPosition() + x = e.page.x - position.x + y = e.page.y - position.y + $('cap_result').value = x + "," + y + submit_captcha() diff --git a/module/web/media/js/base.js b/module/webui/themes/dark/js/render/base.min.js index c68b1047a..1ba1d73f9 100644 --- a/module/web/media/js/base.js +++ b/module/webui/themes/dark/js/render/base.min.js @@ -1,3 +1,3 @@ {% autoescape true %} var LoadJsonToContent,clear_captcha,humanFileSize,load_captcha,on_captcha_click,parseUri,root,set_captcha,submit_captcha;root=this;humanFileSize=function(f){var c,d,e,b;d=new Array("B","KiB","MiB","GiB","TiB","PiB");b=Math.log(f)/Math.log(1024);e=Math.floor(b);c=Math.pow(1024,e);if(f===0){return"0 B"}else{return Math.round(f*100/c)/100+" "+d[e]}};parseUri=function(){var b,c,g,e,d,f,a;b=$("add_links").value;g=new RegExp("(ht|f)tp(s?)://[a-zA-Z0-9-./?=_&%#]+[<| |\"|'|\r|\n|\t]{1}","g");d=b.match(g);if(d===null){return}e="";for(f=0,a=d.length;f<a;f++){c=d[f];if(c.indexOf(" ")!==-1){e=e+c.replace(" "," \n")}else{if(c.indexOf("\t")!==-1){e=e+c.replace("\t"," \n")}else{if(c.indexOf("\r")!==-1){e=e+c.replace("\r"," \n")}else{if(c.indexOf('"')!==-1){e=e+c.replace('"'," \n")}else{if(c.indexOf("<")!==-1){e=e+c.replace("<"," \n")}else{if(c.indexOf("'")!==-1){e=e+c.replace("'"," \n")}else{e=e+c.replace("\n"," \n")}}}}}}}return $("add_links").value=e};Array.prototype.remove=function(d,c){var a,b;a=this.slice((c||d)+1||this.length);this.length=(b=d<0)!=null?b:this.length+{from:d};if(this.length===0){return[]}return this.push.apply(this,a)};document.addEvent("domready",function(){root.notify=new Purr({mode:"top",position:"center"});root.captchaBox=new MooDialog({destroyOnHide:false});root.captchaBox.setContent($("cap_box"));root.addBox=new MooDialog({destroyOnHide:false});root.addBox.setContent($("add_box"));$("add_form").onsubmit=function(){$("add_form").target="upload_target";if($("add_name").value===""&&$("add_file").value===""){alert('{{_("Please Enter a packagename.")}}');return false}else{root.addBox.close();return true}};$("add_reset").addEvent("click",function(){return root.addBox.close()});$("action_add").addEvent("click",function(){$("add_form").reset();return root.addBox.open()});$("action_play").addEvent("click",function(){return new Request({method:"get",url:"/api/unpauseServer"}).send()});$("action_cancel").addEvent("click",function(){return new Request({method:"get",url:"/api/stopAllDownloads"}).send()});$("action_stop").addEvent("click",function(){return new Request({method:"get",url:"/api/pauseServer"}).send()});$("cap_info").addEvent("click",function(){load_captcha("get","");return root.captchaBox.open()});$("cap_reset").addEvent("click",function(){return root.captchaBox.close()});$("cap_form").addEvent("submit",function(a){submit_captcha();return a.stop()});$("cap_positional").addEvent("click",on_captcha_click);return new Request.JSON({url:"/json/status",onSuccess:LoadJsonToContent,secure:false,async:true,initialDelay:0,delay:4000,limit:3000}).startTimer()});LoadJsonToContent=function(a){$("speed").set("text",humanFileSize(a.speed)+"/s");$("aktiv").set("text",a.active);$("aktiv_from").set("text",a.queue);$("aktiv_total").set("text",a.total);if(a.captcha){if($("cap_info").getStyle("display")!=="inline"){$("cap_info").setStyle("display","inline");root.notify.alert('{{_("New Captcha Request")}}',{className:"notify"})}}else{$("cap_info").setStyle("display","none")}if(a.download){$("time").set("text",' {{_("on")}}');$("time").setStyle("background-color","#8ffc25")}else{$("time").set("text",' {{_("off")}}');$("time").setStyle("background-color","#fc6e26")}if(a.reconnect){$("reconnect").set("text",' {{_("on")}}');$("reconnect").setStyle("background-color","#8ffc25")}else{$("reconnect").set("text",' {{_("off")}}');$("reconnect").setStyle("background-color","#fc6e26")}return null};set_captcha=function(a){$("cap_id").set("value",a.id);if(a.result_type==="textual"){$("cap_textual_img").set("src",a.src);$("cap_title").set("text",'{{_("Please read the text on the captcha.")}}');$("cap_submit").setStyle("display","inline");$("cap_textual").setStyle("display","block");return $("cap_positional").setStyle("display","none")}else{if(a.result_type==="positional"){$("cap_positional_img").set("src",a.src);$("cap_title").set("text",'{{_("Please click on the right captcha position.")}}');$("cap_submit").setStyle("display","none");return $("cap_textual").setStyle("display","none")}}};load_captcha=function(b,a){return new Request.JSON({url:"/json/set_captcha",onSuccess:function(c){return set_captcha(c)(c.captcha?void 0:clear_captcha())},secure:false,async:true,method:b}).send(a)};clear_captcha=function(){$("cap_textual").setStyle("display","none");$("cap_textual_img").set("src","");$("cap_positional").setStyle("display","none");$("cap_positional_img").set("src","");return $("cap_title").set("text",'{{_("No Captchas to read.")}}')};submit_captcha=function(){load_captcha("post","cap_id="+$("cap_id").get("value")+"&cap_result="+$("cap_result").get("value"));$("cap_result").set("value","");return false};on_captcha_click=function(c){var b,a,d;b=c.target.getPosition();a=c.page.x-b.x;d=c.page.y-b.y;$("cap_result").value=a+","+d;return submit_captcha()}; -{% endautoescape %}
\ No newline at end of file +{% endautoescape %} diff --git a/module/web/media/js/package_ui.js b/module/webui/themes/dark/js/render/package.js index 3ea965649..659a8e6fc 100644 --- a/module/web/media/js/package_ui.js +++ b/module/webui/themes/dark/js/render/package.js @@ -188,28 +188,28 @@ var Package = new Class({ }, createLinks: function(data) { - var ul = $("sort_children_{id}".substitute({"id": this.id})); + var ul = $("sort_children_{id}".substitute({'id': this.id})); ul.set("html", ""); data.links.each(function(link) { link.id = link.fid; var li = new Element("li", { - "style": { - "margin-left": 0 + 'style': { + 'margin-left': 0 } }); - var html = "<span style='cursor: move' class='child_status sorthandle'><img src='/media/default/img/{icon}' style='width: 12px; height:12px;'/></span>\n".substitute({"icon": link.icon}); - html += "<span style='font-size: 15px'>{name}</span><br /><div class='child_secrow'>".substitute({"name": link.name}); - html += "<span class='child_status'>{statusmsg}</span>{error} ".substitute({"statusmsg": link.statusmsg, "error":link.error}); - html += "<span class='child_status'>{format_size}</span>".substitute({"format_size": link.format_size}); - html += "<span class='child_status'>{plugin}</span> ".substitute({"plugin": link.plugin}); - html += "<img title='{{_("Delete Link")}}' style='cursor: pointer;' width='10px' height='10px' src='/media/default/img/delete.png' /> "; - html += "<img title='{{_("Restart Link")}}' style='cursor: pointer;margin-left: -4px' width='10px' height='10px' src='/media/default/img/arrow_refresh.png' /></div>"; + var html = "<span style='cursor: move' class='child_status sorthandle'><img src='../img/{icon}' style='width: 12px; height:12px;'/></span>\n".substitute({'icon': link.icon}); + html += "<span style='font-size: 15px'><a href=\"{url}\" target=\"_blank\">{name}</a></span><br /><div class='child_secrow'>".substitute({'url': link.url, 'name': link.name}); + html += "<span class='child_status'>{statusmsg}</span>{error} ".substitute({'statusmsg': link.statusmsg, 'error':link.error}); + html += "<span class='child_status'>{format_size}</span>".substitute({'format_size': link.format_size}); + html += "<span class='child_status'>{plugin}</span> ".substitute({'plugin': link.plugin}); + html += "<img title='{{_(\"Delete Link\")}}' style='cursor: pointer;' width='10px' height='10px' src='../img/delete.png' /> "; + html += "<img title='{{_(\"Restart Link\")}}' style='cursor: pointer;margin-left: -4px' width='10px' height='10px' src='../img/arrow_refresh.png' /></div>"; var div = new Element("div", { - "id": "file_" + link.id, - "class": "child", - "html": html + 'id': "file_" + link.id, + 'class': "child", + 'html': html }); li.store("order", link.order); @@ -254,7 +254,7 @@ var Package = new Class({ onSuccess: function() { var ele = $('file_' + this); var imgs = ele.getElements("img"); - imgs[0].set("src", "/media/default/img/status_queue.png"); + imgs[0].set("src", "../img/status_queue.png"); var spans = ele.getElements(".child_status"); spans[1].set("html", "queued"); indicateSuccess(); @@ -313,7 +313,7 @@ var Package = new Class({ if (child.getStyle('display') == "block") { child.dissolve(); } - var ul = $("sort_children_{id}".substitute({"id": this.id})); + var ul = $("sort_children_{id}".substitute({'id': this.id})); ul.erase("html"); this.linksLoaded = false; }, @@ -374,4 +374,3 @@ var Package = new Class({ } }); - diff --git a/module/webui/themes/dark/js/render/settings.coffee b/module/webui/themes/dark/js/render/settings.coffee new file mode 100644 index 000000000..d522741b9 --- /dev/null +++ b/module/webui/themes/dark/js/render/settings.coffee @@ -0,0 +1,107 @@ +root = this + +window.addEvent 'domready', -> + root.accountDialog = new MooDialog {destroyOnHide: false} + root.accountDialog.setContent $ 'account_box' + + new TinyTab $$('#toptabs li a'), $$('#tabs-body > span') + + $$('ul.nav').each (nav) -> + new MooDropMenu nav, { + onOpen: (el) -> el.fade 'in' + onClose: (el) -> el.fade 'out' + onInitialize: (el) -> el.fade('hide').set 'tween', {duration:500} + } + + new SettingsUI() + + +class SettingsUI + constructor: -> + @menu = $$ "#general-menu li" + @menu.append $$ "#plugin-menu li" + + @name = $ "tabsback" + @general = $ "general_form_content" + @plugin = $ "plugin_form_content" + + el.addEvent 'click', @menuClick.bind(this) for el in @menu + + $("general|submit").addEvent "click", @configSubmit.bind(this) + $("plugin|submit").addEvent "click", @configSubmit.bind(this) + + $("account_add").addEvent "click", (e) -> + root.accountDialog.open() + e.stop() + + $("account_reset").addEvent "click", (e) -> + root.accountDialog.close() + + $("account_add_button").addEvent "click", @addAccount.bind(this) + $("account_submit").addEvent "click", @submitAccounts.bind(this) + + + menuClick: (e) -> + [category, section] = e.target.get("id").split("|") + name = e.target.get "text" + + + target = if category is "general" then @general else @plugin + target.dissolve() + + new Request({ + "method" : "get" + "url" : "/json/load_config/#{category}/#{section}" + 'onSuccess': (data) => + target.set "html", data + target.reveal() + this.name.set "text", name + }).send() + + + configSubmit: (e) -> + category = e.target.get("id").split("|")[0] + form = $("#{category}_form") + + form.set "send", { + 'method': "post" + 'url': "/json/save_config/#{category}" + "onSuccess" : -> + root.notify.alert '{{ _("Settings saved.")}}', { + 'className': 'success' + } + 'onFailure': -> + root.notify.alert '{{ _("Error occured.")}}', { + 'className': 'error' + } + } + form.send() + e.stop() + + addAccount: (e) -> + form = $ "add_account_form" + form.set "send", { + 'method': "post" + "onSuccess" : -> window.location.reload() + 'onFailure': -> + root.notify.alert '{{_("Error occured.")}}', { + 'className': 'error' + } + } + + form.send() + e.stop() + + submitAccounts: (e) -> + form = $ "account_form" + form.set "send", { + 'method': "post", + "onSuccess" : -> window.location.reload() + 'onFailure': -> + root.notify.alert('{{ _("Error occured.") }}', { + 'className': 'error' + }) + } + + form.send() + e.stop() diff --git a/module/web/media/js/settings.js b/module/webui/themes/dark/js/render/settings.min.js index 9191fac72..41d1cb25a 100644 --- a/module/web/media/js/settings.js +++ b/module/webui/themes/dark/js/render/settings.min.js @@ -1,3 +1,3 @@ {% autoescape true %} var SettingsUI,root;var __bind=function(a,b){return function(){return a.apply(b,arguments)}};root=this;window.addEvent("domready",function(){root.accountDialog=new MooDialog({destroyOnHide:false});root.accountDialog.setContent($("account_box"));new TinyTab($$("#toptabs li a"),$$("#tabs-body > span"));$$("ul.nav").each(function(a){return new MooDropMenu(a,{onOpen:function(b){return b.fade("in")},onClose:function(b){return b.fade("out")},onInitialize:function(b){return b.fade("hide").set("tween",{duration:500})}})});return new SettingsUI()});SettingsUI=(function(){function a(){var c,e,b,d;this.menu=$$("#general-menu li");this.menu.append($$("#plugin-menu li"));this.name=$("tabsback");this.general=$("general_form_content");this.plugin=$("plugin_form_content");d=this.menu;for(e=0,b=d.length;e<b;e++){c=d[e];c.addEvent("click",this.menuClick.bind(this))}$("general|submit").addEvent("click",this.configSubmit.bind(this));$("plugin|submit").addEvent("click",this.configSubmit.bind(this));$("account_add").addEvent("click",function(f){root.accountDialog.open();return f.stop()});$("account_reset").addEvent("click",function(f){return root.accountDialog.close()});$("account_add_button").addEvent("click",this.addAccount.bind(this));$("account_submit").addEvent("click",this.submitAccounts.bind(this))}a.prototype.menuClick=function(h){var c,b,g,f,d;d=h.target.get("id").split("|"),c=d[0],g=d[1];b=h.target.get("text");f=c==="general"?this.general:this.plugin;f.dissolve();return new Request({method:"get",url:"/json/load_config/"+c+"/"+g,onSuccess:__bind(function(e){f.set("html",e);f.reveal();return this.name.set("text",b)},this)}).send()};a.prototype.configSubmit=function(d){var c,b;c=d.target.get("id").split("|")[0];b=$(""+c+"_form");b.set("send",{method:"post",url:"/json/save_config/"+c,onSuccess:function(){return root.notify.alert('{{ _("Settings saved.")}}',{className:"success"})},onFailure:function(){return root.notify.alert('{{ _("Error occured.")}}',{className:"error"})}});b.send();return d.stop()};a.prototype.addAccount=function(c){var b;b=$("add_account_form");b.set("send",{method:"post",onSuccess:function(){return window.location.reload()},onFailure:function(){return root.notify.alert('{{_("Error occured.")}}',{className:"error"})}});b.send();return c.stop()};a.prototype.submitAccounts=function(c){var b;b=$("account_form");b.set("send",{method:"post",onSuccess:function(){return window.location.reload()},onFailure:function(){return root.notify.alert('{{ _("Error occured.") }}',{className:"error"})}});b.send();return c.stop()};return a})(); -{% endautoescape %}
\ No newline at end of file +{% endautoescape %} diff --git a/module/webui/themes/dark/js/static/MooDialog.js b/module/webui/themes/dark/js/static/MooDialog.js new file mode 100644 index 000000000..45a52496f --- /dev/null +++ b/module/webui/themes/dark/js/static/MooDialog.js @@ -0,0 +1,140 @@ +/* +--- +name: MooDialog +description: The base class of MooDialog +authors: Arian Stolwijk +license: MIT-style license +requires: [Core/Class, Core/Element, Core/Element.Style, Core/Element.Event] +provides: [MooDialog, Element.MooDialog] +... +*/ + + +var MooDialog = new Class({ + + Implements: [Options, Events], + + options: { + 'class': 'MooDialog', + title: null, + scroll: true, // IE + forceScroll: false, + useEscKey: true, + destroyOnHide: true, + autoOpen: true, + closeButton: true, + onInitialize: function(){ + this.wrapper.setStyle('display', 'none'); + }, + onBeforeOpen: function(){ + this.wrapper.setStyle('display', 'block'); + this.fireEvent('show'); + }, + onBeforeClose: function(){ + this.wrapper.setStyle('display', 'none'); + this.fireEvent('hide'); + }/*, + onOpen: function(){}, + onClose: function(){}, + onShow: function(){}, + onHide: function(){}, + onInitialize: function(wrapper){}, + onContentChange: function(content){}*/ + }, + + initialize: function(options){ + this.setOptions(options); + this.options.inject = this.options.inject || document.body; + options = this.options; + + var wrapper = this.wrapper = new Element('div.' + options['class'].replace(' ', '.')).inject(options.inject); + this.content = new Element('div.content').inject(wrapper); + + if (options.title){ + this.title = new Element('div.title').set('text', options.title).inject(wrapper); + wrapper.addClass('MooDialogTitle'); + } + + if (options.closeButton){ + this.closeButton = new Element('a.close', { + events: {click: this.close.bind(this)} + }).inject(wrapper); + } + + + /*<ie6>*/// IE 6 scroll + if ((options.scroll && Browser.ie6) || options.forceScroll){ + wrapper.setStyle('position', 'absolute'); + var position = wrapper.getPosition(options.inject); + window.addEvent('scroll', function(){ + var scroll = document.getScroll(); + wrapper.setPosition({ + x: position.x + scroll.x, + y: position.y + scroll.y + }); + }); + } + /*</ie6>*/ + + if (options.useEscKey){ + // Add event for the esc key + document.addEvent('keydown', function(e){ + if (e.key == 'esc') this.close(); + }.bind(this)); + } + + this.addEvent('hide', function(){ + if (options.destroyOnHide) this.destroy(); + }.bind(this)); + + this.fireEvent('initialize', wrapper); + }, + + setContent: function(){ + var content = Array.from(arguments); + if (content.length == 1) content = content[0]; + + this.content.empty(); + + var type = typeOf(content); + if (['string', 'number'].contains(type)) this.content.set('text', content); + else this.content.adopt(content); + + this.fireEvent('contentChange', this.content); + + return this; + }, + + open: function(){ + this.fireEvent('beforeOpen', this.wrapper).fireEvent('open'); + this.opened = true; + return this; + }, + + close: function(){ + this.fireEvent('beforeClose', this.wrapper).fireEvent('close'); + this.opened = false; + return this; + }, + + destroy: function(){ + this.wrapper.destroy(); + }, + + toElement: function(){ + return this.wrapper; + } + +}); + + +Element.implement({ + + MooDialog: function(options){ + this.store('MooDialog', + new MooDialog(options).setContent(this).open() + ); + return this; + } + +}); diff --git a/module/webui/themes/dark/js/static/MooDialog.min.js b/module/webui/themes/dark/js/static/MooDialog.min.js new file mode 100644 index 000000000..90b3ae100 --- /dev/null +++ b/module/webui/themes/dark/js/static/MooDialog.min.js @@ -0,0 +1 @@ +var MooDialog=new Class({Implements:[Options,Events],options:{"class":"MooDialog",title:null,scroll:!0,forceScroll:!1,useEscKey:!0,destroyOnHide:!0,autoOpen:!0,closeButton:!0,onInitialize:function(){this.wrapper.setStyle("display","none")},onBeforeOpen:function(){this.wrapper.setStyle("display","block"),this.fireEvent("show")},onBeforeClose:function(){this.wrapper.setStyle("display","none"),this.fireEvent("hide")}},initialize:function(t){this.setOptions(t),this.options.inject=this.options.inject||document.body,t=this.options;var e=this.wrapper=new Element("div."+t["class"].replace(" ",".")).inject(t.inject);if(this.content=new Element("div.content").inject(e),t.title&&(this.title=new Element("div.title").set("text",t.title).inject(e),e.addClass("MooDialogTitle")),t.closeButton&&(this.closeButton=new Element("a.close",{events:{click:this.close.bind(this)}}).inject(e)),t.scroll&&Browser.ie6||t.forceScroll){e.setStyle("position","absolute");var n=e.getPosition(t.inject);window.addEvent("scroll",function(){var t=document.getScroll();e.setPosition({x:n.x+t.x,y:n.y+t.y})})}t.useEscKey&&document.addEvent("keydown",function(t){"esc"==t.key&&this.close()}.bind(this)),this.addEvent("hide",function(){t.destroyOnHide&&this.destroy()}.bind(this)),this.fireEvent("initialize",e)},setContent:function(){var t=Array.from(arguments);1==t.length&&(t=t[0]),this.content.empty();var e=typeOf(t);return["string","number"].contains(e)?this.content.set("text",t):this.content.adopt(t),this.fireEvent("contentChange",this.content),this},open:function(){return this.fireEvent("beforeOpen",this.wrapper).fireEvent("open"),this.opened=!0,this},close:function(){return this.fireEvent("beforeClose",this.wrapper).fireEvent("close"),this.opened=!1,this},destroy:function(){this.wrapper.destroy()},toElement:function(){return this.wrapper}});Element.implement({MooDialog:function(t){return this.store("MooDialog",new MooDialog(t).setContent(this).open()),this}});
\ No newline at end of file diff --git a/module/web/media/js/MooDropMenu_static.js b/module/webui/themes/dark/js/static/MooDropMenu.js index b9cd8cc10..ac0fa1874 100644 --- a/module/web/media/js/MooDropMenu_static.js +++ b/module/webui/themes/dark/js/static/MooDropMenu.js @@ -34,7 +34,9 @@ var MooDropMenu = new Class({ mouseoutDelay: 200, mouseoverDelay: 0, listSelector: 'ul', - itemSelector: 'li' + itemSelector: 'li', + openEvent: 'mouseenter', + closeEvent: 'mouseleave' }, initialize: function(menu, options, level){ @@ -50,27 +52,22 @@ var MooDropMenu = new Class({ var parent = el.getParent(options.itemSelector), timer; - parent.addEvents({ + parent.addEvent(options.openEvent, function(){ + parent.store('DropDownOpen', true); - 'mouseenter': function(){ - parent.store('DropDownOpen', true); + clearTimeout(timer); + if (options.mouseoverDelay) timer = this.fireEvent.delay(options.mouseoverDelay, this, ['open', el]); + else this.fireEvent('open', el); - clearTimeout(timer); - if (options.mouseoverDelay) timer = this.fireEvent.delay(options.mouseoverDelay, this, ['open', el]); - else this.fireEvent('open', el); + }.bind(this)).addEvent(options.closeEvent, function(){ + parent.store('DropDownOpen', false); - }.bind(this), + clearTimeout(timer); + timer = (function(){ + if (!parent.retrieve('DropDownOpen')) this.fireEvent('close', el); + }).delay(options.mouseoutDelay, this); - 'mouseleave': function(){ - parent.store('DropDownOpen', false); - - clearTimeout(timer); - timer = (function(){ - if (!parent.retrieve('DropDownOpen')) this.fireEvent('close', el); - }).delay(options.mouseoutDelay, this); - - }.bind(this) - }); + }.bind(this)); }, this); }, diff --git a/module/webui/themes/dark/js/static/MooDropMenu.min.js b/module/webui/themes/dark/js/static/MooDropMenu.min.js new file mode 100644 index 000000000..552ae247a --- /dev/null +++ b/module/webui/themes/dark/js/static/MooDropMenu.min.js @@ -0,0 +1 @@ +var MooDropMenu=new Class({Implements:[Options,Events],options:{onOpen:function(e){e.removeClass("close").addClass("open")},onClose:function(e){e.removeClass("open").addClass("close")},onInitialize:function(e){e.removeClass("open").addClass("close")},mouseoutDelay:200,mouseoverDelay:0,listSelector:"ul",itemSelector:"li",openEvent:"mouseenter",closeEvent:"mouseleave"},initialize:function(e,o){this.setOptions(o),o=this.options;var e=this.menu=document.id(e);e.getElements(o.itemSelector+" > "+o.listSelector).each(function(e){this.fireEvent("initialize",e);var n,t=e.getParent(o.itemSelector);t.addEvent(o.openEvent,function(){t.store("DropDownOpen",!0),clearTimeout(n),o.mouseoverDelay?n=this.fireEvent.delay(o.mouseoverDelay,this,["open",e]):this.fireEvent("open",e)}.bind(this)).addEvent(o.closeEvent,function(){t.store("DropDownOpen",!1),clearTimeout(n),n=function(){t.retrieve("DropDownOpen")||this.fireEvent("close",e)}.delay(o.mouseoutDelay,this)}.bind(this))},this)},toElement:function(){return this.menu}});Element.implement({MooDropMenu:function(e){return this.store("MooDropMenu",new MooDropMenu(this,e))}});
\ No newline at end of file diff --git a/module/webui/themes/dark/js/static/mootools-core.js b/module/webui/themes/dark/js/static/mootools-core.js new file mode 100644 index 000000000..db83850fd --- /dev/null +++ b/module/webui/themes/dark/js/static/mootools-core.js @@ -0,0 +1,5977 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/core/8423c12ffd6a6bfcde9ea22554aec795 + +packager build: + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady + +... +*/ + +/* +--- + +name: Core + +description: The heart of MooTools. + +license: MIT-style license. + +copyright: Copyright (c) 2006-2014 [Valerio Proietti](http://mad4milk.net/). + +authors: The MooTools production team (http://mootools.net/developers/) + +inspiration: + - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) + - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) + +provides: [Core, MooTools, Type, typeOf, instanceOf, Native] + +... +*/ + +(function(){ + +this.MooTools = { + version: '1.5.0', + build: '0f7b690afee9349b15909f33016a25d2e4d9f4e3' +}; + +// typeOf, instanceOf + +var typeOf = this.typeOf = function(item){ + if (item == null) return 'null'; + if (item.$family != null) return item.$family(); + + if (item.nodeName){ + if (item.nodeType == 1) return 'element'; + if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; + } else if (typeof item.length == 'number'){ + if ('callee' in item) return 'arguments'; + if ('item' in item) return 'collection'; + } + + return typeof item; +}; + +var instanceOf = this.instanceOf = function(item, object){ + if (item == null) return false; + var constructor = item.$constructor || item.constructor; + while (constructor){ + if (constructor === object) return true; + constructor = constructor.parent; + } + /*<ltIE8>*/ + if (!item.hasOwnProperty) return false; + /*</ltIE8>*/ + return item instanceof object; +}; + +// Function overloading + +var Function = this.Function; + +var enumerables = true; +for (var i in {toString: 1}) enumerables = null; +if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; + +Function.prototype.overloadSetter = function(usePlural){ + var self = this; + return function(a, b){ + if (a == null) return this; + if (usePlural || typeof a != 'string'){ + for (var k in a) self.call(this, k, a[k]); + if (enumerables) for (var i = enumerables.length; i--;){ + k = enumerables[i]; + if (a.hasOwnProperty(k)) self.call(this, k, a[k]); + } + } else { + self.call(this, a, b); + } + return this; + }; +}; + +Function.prototype.overloadGetter = function(usePlural){ + var self = this; + return function(a){ + var args, result; + if (typeof a != 'string') args = a; + else if (arguments.length > 1) args = arguments; + else if (usePlural) args = [a]; + if (args){ + result = {}; + for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); + } else { + result = self.call(this, a); + } + return result; + }; +}; + +Function.prototype.extend = function(key, value){ + this[key] = value; +}.overloadSetter(); + +Function.prototype.implement = function(key, value){ + this.prototype[key] = value; +}.overloadSetter(); + +// From + +var slice = Array.prototype.slice; + +Function.from = function(item){ + return (typeOf(item) == 'function') ? item : function(){ + return item; + }; +}; + +Array.from = function(item){ + if (item == null) return []; + return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; +}; + +Number.from = function(item){ + var number = parseFloat(item); + return isFinite(number) ? number : null; +}; + +String.from = function(item){ + return item + ''; +}; + +// hide, protect + +Function.implement({ + + hide: function(){ + this.$hidden = true; + return this; + }, + + protect: function(){ + this.$protected = true; + return this; + } + +}); + +// Type + +var Type = this.Type = function(name, object){ + if (name){ + var lower = name.toLowerCase(); + var typeCheck = function(item){ + return (typeOf(item) == lower); + }; + + Type['is' + name] = typeCheck; + if (object != null){ + object.prototype.$family = (function(){ + return lower; + }).hide(); + + } + } + + if (object == null) return null; + + object.extend(this); + object.$constructor = Type; + object.prototype.$constructor = object; + + return object; +}; + +var toString = Object.prototype.toString; + +Type.isEnumerable = function(item){ + return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); +}; + +var hooks = {}; + +var hooksOf = function(object){ + var type = typeOf(object.prototype); + return hooks[type] || (hooks[type] = []); +}; + +var implement = function(name, method){ + if (method && method.$hidden) return; + + var hooks = hooksOf(this); + + for (var i = 0; i < hooks.length; i++){ + var hook = hooks[i]; + if (typeOf(hook) == 'type') implement.call(hook, name, method); + else hook.call(this, name, method); + } + + var previous = this.prototype[name]; + if (previous == null || !previous.$protected) this.prototype[name] = method; + + if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ + return method.apply(item, slice.call(arguments, 1)); + }); +}; + +var extend = function(name, method){ + if (method && method.$hidden) return; + var previous = this[name]; + if (previous == null || !previous.$protected) this[name] = method; +}; + +Type.implement({ + + implement: implement.overloadSetter(), + + extend: extend.overloadSetter(), + + alias: function(name, existing){ + implement.call(this, name, this.prototype[existing]); + }.overloadSetter(), + + mirror: function(hook){ + hooksOf(this).push(hook); + return this; + } + +}); + +new Type('Type', Type); + +// Default Types + +var force = function(name, object, methods){ + var isType = (object != Object), + prototype = object.prototype; + + if (isType) object = new Type(name, object); + + for (var i = 0, l = methods.length; i < l; i++){ + var key = methods[i], + generic = object[key], + proto = prototype[key]; + + if (generic) generic.protect(); + if (isType && proto) object.implement(key, proto.protect()); + } + + if (isType){ + var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]); + object.forEachMethod = function(fn){ + if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){ + fn.call(prototype, prototype[methods[i]], methods[i]); + } + for (var key in prototype) fn.call(prototype, prototype[key], key); + }; + } + + return force; +}; + +force('String', String, [ + 'charAt', 'charCodeAt', 'concat', 'contains', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', + 'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase' +])('Array', Array, [ + 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', + 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' +])('Number', Number, [ + 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' +])('Function', Function, [ + 'apply', 'call', 'bind' +])('RegExp', RegExp, [ + 'exec', 'test' +])('Object', Object, [ + 'create', 'defineProperty', 'defineProperties', 'keys', + 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', + 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' +])('Date', Date, ['now']); + +Object.extend = extend.overloadSetter(); + +Date.extend('now', function(){ + return +(new Date); +}); + +new Type('Boolean', Boolean); + +// fixes NaN returning as Number + +Number.prototype.$family = function(){ + return isFinite(this) ? 'number' : 'null'; +}.hide(); + +// Number.random + +Number.extend('random', function(min, max){ + return Math.floor(Math.random() * (max - min + 1) + min); +}); + +// forEach, each + +var hasOwnProperty = Object.prototype.hasOwnProperty; +Object.extend('forEach', function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); + } +}); + +Object.each = Object.forEach; + +Array.implement({ + + /*<!ES5>*/ + forEach: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) fn.call(bind, this[i], i, this); + } + }, + /*</!ES5>*/ + + each: function(fn, bind){ + Array.forEach(this, fn, bind); + return this; + } + +}); + +// Array & Object cloning, Object merging and appending + +var cloneOf = function(item){ + switch (typeOf(item)){ + case 'array': return item.clone(); + case 'object': return Object.clone(item); + default: return item; + } +}; + +Array.implement('clone', function(){ + var i = this.length, clone = new Array(i); + while (i--) clone[i] = cloneOf(this[i]); + return clone; +}); + +var mergeOne = function(source, key, current){ + switch (typeOf(current)){ + case 'object': + if (typeOf(source[key]) == 'object') Object.merge(source[key], current); + else source[key] = Object.clone(current); + break; + case 'array': source[key] = current.clone(); break; + default: source[key] = current; + } + return source; +}; + +Object.extend({ + + merge: function(source, k, v){ + if (typeOf(k) == 'string') return mergeOne(source, k, v); + for (var i = 1, l = arguments.length; i < l; i++){ + var object = arguments[i]; + for (var key in object) mergeOne(source, key, object[key]); + } + return source; + }, + + clone: function(object){ + var clone = {}; + for (var key in object) clone[key] = cloneOf(object[key]); + return clone; + }, + + append: function(original){ + for (var i = 1, l = arguments.length; i < l; i++){ + var extended = arguments[i] || {}; + for (var key in extended) original[key] = extended[key]; + } + return original; + } + +}); + +// Object-less types + +['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ + new Type(name); +}); + +// Unique ID + +var UID = Date.now(); + +String.extend('uniqueID', function(){ + return (UID++).toString(36); +}); + + + +})(); + + +/* +--- + +name: Array + +description: Contains Array Prototypes like each, contains, and erase. + +license: MIT-style license. + +requires: [Type] + +provides: Array + +... +*/ + +Array.implement({ + + /*<!ES5>*/ + every: function(fn, bind){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ + if ((i in this) && !fn.call(bind, this[i], i, this)) return false; + } + return true; + }, + + filter: function(fn, bind){ + var results = []; + for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){ + value = this[i]; + if (fn.call(bind, value, i, this)) results.push(value); + } + return results; + }, + + indexOf: function(item, from){ + var length = this.length >>> 0; + for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){ + if (this[i] === item) return i; + } + return -1; + }, + + map: function(fn, bind){ + var length = this.length >>> 0, results = Array(length); + for (var i = 0; i < length; i++){ + if (i in this) results[i] = fn.call(bind, this[i], i, this); + } + return results; + }, + + some: function(fn, bind){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ + if ((i in this) && fn.call(bind, this[i], i, this)) return true; + } + return false; + }, + /*</!ES5>*/ + + clean: function(){ + return this.filter(function(item){ + return item != null; + }); + }, + + invoke: function(methodName){ + var args = Array.slice(arguments, 1); + return this.map(function(item){ + return item[methodName].apply(item, args); + }); + }, + + associate: function(keys){ + var obj = {}, length = Math.min(this.length, keys.length); + for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; + return obj; + }, + + link: function(object){ + var result = {}; + for (var i = 0, l = this.length; i < l; i++){ + for (var key in object){ + if (object[key](this[i])){ + result[key] = this[i]; + delete object[key]; + break; + } + } + } + return result; + }, + + contains: function(item, from){ + return this.indexOf(item, from) != -1; + }, + + append: function(array){ + this.push.apply(this, array); + return this; + }, + + getLast: function(){ + return (this.length) ? this[this.length - 1] : null; + }, + + getRandom: function(){ + return (this.length) ? this[Number.random(0, this.length - 1)] : null; + }, + + include: function(item){ + if (!this.contains(item)) this.push(item); + return this; + }, + + combine: function(array){ + for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); + return this; + }, + + erase: function(item){ + for (var i = this.length; i--;){ + if (this[i] === item) this.splice(i, 1); + } + return this; + }, + + empty: function(){ + this.length = 0; + return this; + }, + + flatten: function(){ + var array = []; + for (var i = 0, l = this.length; i < l; i++){ + var type = typeOf(this[i]); + if (type == 'null') continue; + array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); + } + return array; + }, + + pick: function(){ + for (var i = 0, l = this.length; i < l; i++){ + if (this[i] != null) return this[i]; + } + return null; + }, + + hexToRgb: function(array){ + if (this.length != 3) return null; + var rgb = this.map(function(value){ + if (value.length == 1) value += value; + return parseInt(value, 16); + }); + return (array) ? rgb : 'rgb(' + rgb + ')'; + }, + + rgbToHex: function(array){ + if (this.length < 3) return null; + if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; + var hex = []; + for (var i = 0; i < 3; i++){ + var bit = (this[i] - 0).toString(16); + hex.push((bit.length == 1) ? '0' + bit : bit); + } + return (array) ? hex : '#' + hex.join(''); + } + +}); + + + + +/* +--- + +name: String + +description: Contains String Prototypes like camelCase, capitalize, test, and toInt. + +license: MIT-style license. + +requires: [Type, Array] + +provides: String + +... +*/ + +String.implement({ + + //<!ES6> + contains: function(string, index){ + return (index ? String(this).slice(index) : String(this)).indexOf(string) > -1; + }, + //</!ES6> + + test: function(regex, params){ + return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); + }, + + trim: function(){ + return String(this).replace(/^\s+|\s+$/g, ''); + }, + + clean: function(){ + return String(this).replace(/\s+/g, ' ').trim(); + }, + + camelCase: function(){ + return String(this).replace(/-\D/g, function(match){ + return match.charAt(1).toUpperCase(); + }); + }, + + hyphenate: function(){ + return String(this).replace(/[A-Z]/g, function(match){ + return ('-' + match.charAt(0).toLowerCase()); + }); + }, + + capitalize: function(){ + return String(this).replace(/\b[a-z]/g, function(match){ + return match.toUpperCase(); + }); + }, + + escapeRegExp: function(){ + return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + hexToRgb: function(array){ + var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); + return (hex) ? hex.slice(1).hexToRgb(array) : null; + }, + + rgbToHex: function(array){ + var rgb = String(this).match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHex(array) : null; + }, + + substitute: function(object, regexp){ + return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ + if (match.charAt(0) == '\\') return match.slice(1); + return (object[name] != null) ? object[name] : ''; + }); + } + +}); + + + + +/* +--- + +name: Number + +description: Contains Number Prototypes like limit, round, times, and ceil. + +license: MIT-style license. + +requires: Type + +provides: Number + +... +*/ + +Number.implement({ + + limit: function(min, max){ + return Math.min(max, Math.max(min, this)); + }, + + round: function(precision){ + precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); + return Math.round(this * precision) / precision; + }, + + times: function(fn, bind){ + for (var i = 0; i < this; i++) fn.call(bind, i, this); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + } + +}); + +Number.alias('each', 'times'); + +(function(math){ + var methods = {}; + math.each(function(name){ + if (!Number[name]) methods[name] = function(){ + return Math[name].apply(null, [this].concat(Array.from(arguments))); + }; + }); + Number.implement(methods); +})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); + + +/* +--- + +name: Function + +description: Contains Function Prototypes like create, bind, pass, and delay. + +license: MIT-style license. + +requires: Type + +provides: Function + +... +*/ + +Function.extend({ + + attempt: function(){ + for (var i = 0, l = arguments.length; i < l; i++){ + try { + return arguments[i](); + } catch (e){} + } + return null; + } + +}); + +Function.implement({ + + attempt: function(args, bind){ + try { + return this.apply(bind, Array.from(args)); + } catch (e){} + + return null; + }, + + /*<!ES5-bind>*/ + bind: function(that){ + var self = this, + args = arguments.length > 1 ? Array.slice(arguments, 1) : null, + F = function(){}; + + var bound = function(){ + var context = that, length = arguments.length; + if (this instanceof bound){ + F.prototype = self.prototype; + context = new F; + } + var result = (!args && !length) + ? self.call(context) + : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments); + return context == that ? result : context; + }; + return bound; + }, + /*</!ES5-bind>*/ + + pass: function(args, bind){ + var self = this; + if (args != null) args = Array.from(args); + return function(){ + return self.apply(bind, args || arguments); + }; + }, + + delay: function(delay, bind, args){ + return setTimeout(this.pass((args == null ? [] : args), bind), delay); + }, + + periodical: function(periodical, bind, args){ + return setInterval(this.pass((args == null ? [] : args), bind), periodical); + } + +}); + + + + +/* +--- + +name: Object + +description: Object generic methods + +license: MIT-style license. + +requires: Type + +provides: [Object, Hash] + +... +*/ + +(function(){ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +Object.extend({ + + subset: function(object, keys){ + var results = {}; + for (var i = 0, l = keys.length; i < l; i++){ + var k = keys[i]; + if (k in object) results[k] = object[k]; + } + return results; + }, + + map: function(object, fn, bind){ + var results = {}; + for (var key in object){ + if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object); + } + return results; + }, + + filter: function(object, fn, bind){ + var results = {}; + for (var key in object){ + var value = object[key]; + if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value; + } + return results; + }, + + every: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false; + } + return true; + }, + + some: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true; + } + return false; + }, + + keys: function(object){ + var keys = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) keys.push(key); + } + return keys; + }, + + values: function(object){ + var values = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) values.push(object[key]); + } + return values; + }, + + getLength: function(object){ + return Object.keys(object).length; + }, + + keyOf: function(object, value){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && object[key] === value) return key; + } + return null; + }, + + contains: function(object, value){ + return Object.keyOf(object, value) != null; + }, + + toQueryString: function(object, base){ + var queryString = []; + + Object.each(object, function(value, key){ + if (base) key = base + '[' + key + ']'; + var result; + switch (typeOf(value)){ + case 'object': result = Object.toQueryString(value, key); break; + case 'array': + var qs = {}; + value.each(function(val, i){ + qs[i] = val; + }); + result = Object.toQueryString(qs, key); + break; + default: result = key + '=' + encodeURIComponent(value); + } + if (value != null) queryString.push(result); + }); + + return queryString.join('&'); + } + +}); + +})(); + + + + +/* +--- + +name: Browser + +description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. + +license: MIT-style license. + +requires: [Array, Function, Number, String] + +provides: [Browser, Window, Document] + +... +*/ + +(function(){ + +var document = this.document; +var window = document.window = this; + +var parse = function(ua, platform){ + ua = ua.toLowerCase(); + platform = (platform ? platform.toLowerCase() : ''); + + var UA = ua.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/) || [null, 'unknown', 0]; + + if (UA[1] == 'trident'){ + UA[1] = 'ie'; + if (UA[4]) UA[2] = UA[4]; + } else if (UA[1] == 'crios') { + UA[1] = 'chrome'; + } + + var platform = ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]; + if (platform == 'win') platform = 'windows'; + + return { + extend: Function.prototype.extend, + name: (UA[1] == 'version') ? UA[3] : UA[1], + version: parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), + platform: platform + }; +}; + +var Browser = this.Browser = parse(navigator.userAgent, navigator.platform); + +if (Browser.ie){ + Browser.version = document.documentMode; +} + +Browser.extend({ + Features: { + xpath: !!(document.evaluate), + air: !!(window.runtime), + query: !!(document.querySelector), + json: !!(window.JSON) + }, + parseUA: parse +}); + + + +// Request + +Browser.Request = (function(){ + + var XMLHTTP = function(){ + return new XMLHttpRequest(); + }; + + var MSXML2 = function(){ + return new ActiveXObject('MSXML2.XMLHTTP'); + }; + + var MSXML = function(){ + return new ActiveXObject('Microsoft.XMLHTTP'); + }; + + return Function.attempt(function(){ + XMLHTTP(); + return XMLHTTP; + }, function(){ + MSXML2(); + return MSXML2; + }, function(){ + MSXML(); + return MSXML; + }); + +})(); + +Browser.Features.xhr = !!(Browser.Request); + + + +// String scripts + +Browser.exec = function(text){ + if (!text) return text; + if (window.execScript){ + window.execScript(text); + } else { + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.text = text; + document.head.appendChild(script); + document.head.removeChild(script); + } + return text; +}; + +String.implement('stripScripts', function(exec){ + var scripts = ''; + var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){ + scripts += code + '\n'; + return ''; + }); + if (exec === true) Browser.exec(scripts); + else if (typeOf(exec) == 'function') exec(scripts, text); + return text; +}); + +// Window, Document + +Browser.extend({ + Document: this.Document, + Window: this.Window, + Element: this.Element, + Event: this.Event +}); + +this.Window = this.$constructor = new Type('Window', function(){}); + +this.$family = Function.from('window').hide(); + +Window.mirror(function(name, method){ + window[name] = method; +}); + +this.Document = document.$constructor = new Type('Document', function(){}); + +document.$family = Function.from('document').hide(); + +Document.mirror(function(name, method){ + document[name] = method; +}); + +document.html = document.documentElement; +if (!document.head) document.head = document.getElementsByTagName('head')[0]; + +if (document.execCommand) try { + document.execCommand("BackgroundImageCache", false, true); +} catch (e){} + +/*<ltIE9>*/ +if (this.attachEvent && !this.addEventListener){ + var unloadEvent = function(){ + this.detachEvent('onunload', unloadEvent); + document.head = document.html = document.window = null; + }; + this.attachEvent('onunload', unloadEvent); +} + +// IE fails on collections and <select>.options (refers to <select>) +var arrayFrom = Array.from; +try { + arrayFrom(document.html.childNodes); +} catch(e){ + Array.from = function(item){ + if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ + var i = item.length, array = new Array(i); + while (i--) array[i] = item[i]; + return array; + } + return arrayFrom(item); + }; + + var prototype = Array.prototype, + slice = prototype.slice; + ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ + var method = prototype[name]; + Array[name] = function(item){ + return method.apply(Array.from(item), slice.call(arguments, 1)); + }; + }); +} +/*</ltIE9>*/ + + + +})(); + + +/* +--- + +name: Event + +description: Contains the Event Type, to make the event object cross-browser. + +license: MIT-style license. + +requires: [Window, Document, Array, Function, String, Object] + +provides: Event + +... +*/ + +(function() { + +var _keys = {}; + +var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){ + if (!win) win = window; + event = event || win.event; + if (event.$extended) return event; + this.event = event; + this.$extended = true; + this.shift = event.shiftKey; + this.control = event.ctrlKey; + this.alt = event.altKey; + this.meta = event.metaKey; + var type = this.type = event.type; + var target = event.target || event.srcElement; + while (target && target.nodeType == 3) target = target.parentNode; + this.target = document.id(target); + + if (type.indexOf('key') == 0){ + var code = this.code = (event.which || event.keyCode); + this.key = _keys[code]; + if (type == 'keydown' || type == 'keyup'){ + if (code > 111 && code < 124) this.key = 'f' + (code - 111); + else if (code > 95 && code < 106) this.key = code - 96; + } + if (this.key == null) this.key = String.fromCharCode(code).toLowerCase(); + } else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){ + var doc = win.document; + doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; + this.page = { + x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, + y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop + }; + this.client = { + x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, + y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY + }; + if (type == 'DOMMouseScroll' || type == 'mousewheel') + this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; + + this.rightClick = (event.which == 3 || event.button == 2); + if (type == 'mouseover' || type == 'mouseout'){ + var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; + while (related && related.nodeType == 3) related = related.parentNode; + this.relatedTarget = document.id(related); + } + } else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){ + this.rotation = event.rotation; + this.scale = event.scale; + this.targetTouches = event.targetTouches; + this.changedTouches = event.changedTouches; + var touches = this.touches = event.touches; + if (touches && touches[0]){ + var touch = touches[0]; + this.page = {x: touch.pageX, y: touch.pageY}; + this.client = {x: touch.clientX, y: touch.clientY}; + } + } + + if (!this.client) this.client = {}; + if (!this.page) this.page = {}; +}); + +DOMEvent.implement({ + + stop: function(){ + return this.preventDefault().stopPropagation(); + }, + + stopPropagation: function(){ + if (this.event.stopPropagation) this.event.stopPropagation(); + else this.event.cancelBubble = true; + return this; + }, + + preventDefault: function(){ + if (this.event.preventDefault) this.event.preventDefault(); + else this.event.returnValue = false; + return this; + } + +}); + +DOMEvent.defineKey = function(code, key){ + _keys[code] = key; + return this; +}; + +DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true); + +DOMEvent.defineKeys({ + '38': 'up', '40': 'down', '37': 'left', '39': 'right', + '27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab', + '46': 'delete', '13': 'enter' +}); + +})(); + + + + + + +/* +--- + +name: Class + +description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. + +license: MIT-style license. + +requires: [Array, String, Function, Number] + +provides: Class + +... +*/ + +(function(){ + +var Class = this.Class = new Type('Class', function(params){ + if (instanceOf(params, Function)) params = {initialize: params}; + + var newClass = function(){ + reset(this); + if (newClass.$prototyping) return this; + this.$caller = null; + var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; + this.$caller = this.caller = null; + return value; + }.extend(this).implement(params); + + newClass.$constructor = Class; + newClass.prototype.$constructor = newClass; + newClass.prototype.parent = parent; + + return newClass; +}); + +var parent = function(){ + if (!this.$caller) throw new Error('The method "parent" cannot be called.'); + var name = this.$caller.$name, + parent = this.$caller.$owner.parent, + previous = (parent) ? parent.prototype[name] : null; + if (!previous) throw new Error('The method "' + name + '" has no parent.'); + return previous.apply(this, arguments); +}; + +var reset = function(object){ + for (var key in object){ + var value = object[key]; + switch (typeOf(value)){ + case 'object': + var F = function(){}; + F.prototype = value; + object[key] = reset(new F); + break; + case 'array': object[key] = value.clone(); break; + } + } + return object; +}; + +var wrap = function(self, key, method){ + if (method.$origin) method = method.$origin; + var wrapper = function(){ + if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); + var caller = this.caller, current = this.$caller; + this.caller = current; this.$caller = wrapper; + var result = method.apply(this, arguments); + this.$caller = current; this.caller = caller; + return result; + }.extend({$owner: self, $origin: method, $name: key}); + return wrapper; +}; + +var implement = function(key, value, retain){ + if (Class.Mutators.hasOwnProperty(key)){ + value = Class.Mutators[key].call(this, value); + if (value == null) return this; + } + + if (typeOf(value) == 'function'){ + if (value.$hidden) return this; + this.prototype[key] = (retain) ? value : wrap(this, key, value); + } else { + Object.merge(this.prototype, key, value); + } + + return this; +}; + +var getInstance = function(klass){ + klass.$prototyping = true; + var proto = new klass; + delete klass.$prototyping; + return proto; +}; + +Class.implement('implement', implement.overloadSetter()); + +Class.Mutators = { + + Extends: function(parent){ + this.parent = parent; + this.prototype = getInstance(parent); + }, + + Implements: function(items){ + Array.from(items).each(function(item){ + var instance = new item; + for (var key in instance) implement.call(this, key, instance[key], true); + }, this); + } +}; + +})(); + + +/* +--- + +name: Class.Extras + +description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. + +license: MIT-style license. + +requires: Class + +provides: [Class.Extras, Chain, Events, Options] + +... +*/ + +(function(){ + +this.Chain = new Class({ + + $chain: [], + + chain: function(){ + this.$chain.append(Array.flatten(arguments)); + return this; + }, + + callChain: function(){ + return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; + }, + + clearChain: function(){ + this.$chain.empty(); + return this; + } + +}); + +var removeOn = function(string){ + return string.replace(/^on([A-Z])/, function(full, first){ + return first.toLowerCase(); + }); +}; + +this.Events = new Class({ + + $events: {}, + + addEvent: function(type, fn, internal){ + type = removeOn(type); + + + + this.$events[type] = (this.$events[type] || []).include(fn); + if (internal) fn.internal = true; + return this; + }, + + addEvents: function(events){ + for (var type in events) this.addEvent(type, events[type]); + return this; + }, + + fireEvent: function(type, args, delay){ + type = removeOn(type); + var events = this.$events[type]; + if (!events) return this; + args = Array.from(args); + events.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + removeEvent: function(type, fn){ + type = removeOn(type); + var events = this.$events[type]; + if (events && !fn.internal){ + var index = events.indexOf(fn); + if (index != -1) delete events[index]; + } + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + if (events) events = removeOn(events); + for (type in this.$events){ + if (events && events != type) continue; + var fns = this.$events[type]; + for (var i = fns.length; i--;) if (i in fns){ + this.removeEvent(type, fns[i]); + } + } + return this; + } + +}); + +this.Options = new Class({ + + setOptions: function(){ + var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments)); + if (this.addEvent) for (var option in options){ + if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; + this.addEvent(option, options[option]); + delete options[option]; + } + return this; + } + +}); + +})(); + + +/* +--- +name: Slick.Parser +description: Standalone CSS3 Selector parser +provides: Slick.Parser +... +*/ + +;(function(){ + +var parsed, + separatorIndex, + combinatorIndex, + reversed, + cache = {}, + reverseCache = {}, + reUnescape = /\\/g; + +var parse = function(expression, isReversed){ + if (expression == null) return null; + if (expression.Slick === true) return expression; + expression = ('' + expression).replace(/^\s+|\s+$/g, ''); + reversed = !!isReversed; + var currentCache = (reversed) ? reverseCache : cache; + if (currentCache[expression]) return currentCache[expression]; + parsed = { + Slick: true, + expressions: [], + raw: expression, + reverse: function(){ + return parse(this.raw, true); + } + }; + separatorIndex = -1; + while (expression != (expression = expression.replace(regexp, parser))); + parsed.length = parsed.expressions.length; + return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed; +}; + +var reverseCombinator = function(combinator){ + if (combinator === '!') return ' '; + else if (combinator === ' ') return '!'; + else if ((/^!/).test(combinator)) return combinator.replace(/^!/, ''); + else return '!' + combinator; +}; + +var reverse = function(expression){ + var expressions = expression.expressions; + for (var i = 0; i < expressions.length; i++){ + var exp = expressions[i]; + var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)}; + + for (var j = 0; j < exp.length; j++){ + var cexp = exp[j]; + if (!cexp.reverseCombinator) cexp.reverseCombinator = ' '; + cexp.combinator = cexp.reverseCombinator; + delete cexp.reverseCombinator; + } + + exp.reverse().push(last); + } + return expression; +}; + +var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License + return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){ + return '\\' + match; + }); +}; + +var regexp = new RegExp( +/* +#!/usr/bin/env ruby +puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'') +__END__ + "(?x)^(?:\ + \\s* ( , ) \\s* # Separator \n\ + | \\s* ( <combinator>+ ) \\s* # Combinator \n\ + | ( \\s+ ) # CombinatorChildren \n\ + | ( <unicode>+ | \\* ) # Tag \n\ + | \\# ( <unicode>+ ) # ID \n\ + | \\. ( <unicode>+ ) # ClassName \n\ + | # Attribute \n\ + \\[ \ + \\s* (<unicode1>+) (?: \ + \\s* ([*^$!~|]?=) (?: \ + \\s* (?:\ + ([\"']?)(.*?)\\9 \ + )\ + ) \ + )? \\s* \ + \\](?!\\]) \n\ + | :+ ( <unicode>+ )(?:\ + \\( (?:\ + (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\ + ) \\)\ + )?\ + )" +*/ + "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)" + .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']') + .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') + .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') +); + +function parser( + rawMatch, + + separator, + combinator, + combinatorChildren, + + tagName, + id, + className, + + attributeKey, + attributeOperator, + attributeQuote, + attributeValue, + + pseudoMarker, + pseudoClass, + pseudoQuote, + pseudoClassQuotedValue, + pseudoClassValue +){ + if (separator || separatorIndex === -1){ + parsed.expressions[++separatorIndex] = []; + combinatorIndex = -1; + if (separator) return ''; + } + + if (combinator || combinatorChildren || combinatorIndex === -1){ + combinator = combinator || ' '; + var currentSeparator = parsed.expressions[separatorIndex]; + if (reversed && currentSeparator[combinatorIndex]) + currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator); + currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'}; + } + + var currentParsed = parsed.expressions[separatorIndex][combinatorIndex]; + + if (tagName){ + currentParsed.tag = tagName.replace(reUnescape, ''); + + } else if (id){ + currentParsed.id = id.replace(reUnescape, ''); + + } else if (className){ + className = className.replace(reUnescape, ''); + + if (!currentParsed.classList) currentParsed.classList = []; + if (!currentParsed.classes) currentParsed.classes = []; + currentParsed.classList.push(className); + currentParsed.classes.push({ + value: className, + regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') + }); + + } else if (pseudoClass){ + pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue; + pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null; + + if (!currentParsed.pseudos) currentParsed.pseudos = []; + currentParsed.pseudos.push({ + key: pseudoClass.replace(reUnescape, ''), + value: pseudoClassValue, + type: pseudoMarker.length == 1 ? 'class' : 'element' + }); + + } else if (attributeKey){ + attributeKey = attributeKey.replace(reUnescape, ''); + attributeValue = (attributeValue || '').replace(reUnescape, ''); + + var test, regexp; + + switch (attributeOperator){ + case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break; + case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break; + case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break; + case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break; + case '=' : test = function(value){ + return attributeValue == value; + }; break; + case '*=' : test = function(value){ + return value && value.indexOf(attributeValue) > -1; + }; break; + case '!=' : test = function(value){ + return attributeValue != value; + }; break; + default : test = function(value){ + return !!value; + }; + } + + if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){ + return false; + }; + + if (!test) test = function(value){ + return value && regexp.test(value); + }; + + if (!currentParsed.attributes) currentParsed.attributes = []; + currentParsed.attributes.push({ + key: attributeKey, + operator: attributeOperator, + value: attributeValue, + test: test + }); + + } + + return ''; +}; + +// Slick NS + +var Slick = (this.Slick || {}); + +Slick.parse = function(expression){ + return parse(expression); +}; + +Slick.escapeRegExp = escapeRegExp; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); + + +/* +--- +name: Slick.Finder +description: The new, superfast css selector engine. +provides: Slick.Finder +requires: Slick.Parser +... +*/ + +;(function(){ + +var local = {}, + featuresCache = {}, + toString = Object.prototype.toString; + +// Feature / Bug detection + +local.isNativeCode = function(fn){ + return (/\{\s*\[native code\]\s*\}/).test('' + fn); +}; + +local.isXML = function(document){ + return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') || + (document.nodeType == 9 && document.documentElement.nodeName != 'HTML'); +}; + +local.setDocument = function(document){ + + // convert elements / window arguments to document. if document cannot be extrapolated, the function returns. + var nodeType = document.nodeType; + if (nodeType == 9); // document + else if (nodeType) document = document.ownerDocument; // node + else if (document.navigator) document = document.document; // window + else return; + + // check if it's the old document + + if (this.document === document) return; + this.document = document; + + // check if we have done feature detection on this document before + + var root = document.documentElement, + rootUid = this.getUIDXML(root), + features = featuresCache[rootUid], + feature; + + if (features){ + for (feature in features){ + this[feature] = features[feature]; + } + return; + } + + features = featuresCache[rootUid] = {}; + + features.root = root; + features.isXMLDocument = this.isXML(document); + + features.brokenStarGEBTN + = features.starSelectsClosedQSA + = features.idGetsName + = features.brokenMixedCaseQSA + = features.brokenGEBCN + = features.brokenCheckedQSA + = features.brokenEmptyAttributeQSA + = features.isHTMLDocument + = features.nativeMatchesSelector + = false; + + var starSelectsClosed, starSelectsComments, + brokenSecondClassNameGEBCN, cachedGetElementsByClassName, + brokenFormAttributeGetter; + + var selected, id = 'slick_uniqueid'; + var testNode = document.createElement('div'); + + var testRoot = document.body || document.getElementsByTagName('body')[0] || root; + testRoot.appendChild(testNode); + + // on non-HTML documents innerHTML and getElementsById doesnt work properly + try { + testNode.innerHTML = '<a id="'+id+'"></a>'; + features.isHTMLDocument = !!document.getElementById(id); + } catch(e){}; + + if (features.isHTMLDocument){ + + testNode.style.display = 'none'; + + // IE returns comment nodes for getElementsByTagName('*') for some documents + testNode.appendChild(document.createComment('')); + starSelectsComments = (testNode.getElementsByTagName('*').length > 1); + + // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents + try { + testNode.innerHTML = 'foo</foo>'; + selected = testNode.getElementsByTagName('*'); + starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + features.brokenStarGEBTN = starSelectsComments || starSelectsClosed; + + // IE returns elements with the name instead of just id for getElementsById for some documents + try { + testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>'; + features.idGetsName = document.getElementById(id) === testNode.firstChild; + } catch(e){}; + + if (testNode.getElementsByClassName){ + + // Safari 3.2 getElementsByClassName caches results + try { + testNode.innerHTML = '<a class="f"></a><a class="b"></a>'; + testNode.getElementsByClassName('b').length; + testNode.firstChild.className = 'b'; + cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2); + } catch(e){}; + + // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one + try { + testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>'; + brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); + } catch(e){}; + + features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; + } + + if (testNode.querySelectorAll){ + // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents + try { + testNode.innerHTML = 'foo</foo>'; + selected = testNode.querySelectorAll('*'); + features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode + try { + testNode.innerHTML = '<a class="MiX"></a>'; + features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length; + } catch(e){}; + + // Webkit and Opera dont return selected options on querySelectorAll + try { + testNode.innerHTML = '<select><option selected="selected">a</option></select>'; + features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0); + } catch(e){}; + + // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll + try { + testNode.innerHTML = '<a class=""></a>'; + features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0); + } catch(e){}; + + } + + // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input + try { + testNode.innerHTML = '<form action="s"><input id="action"/></form>'; + brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's'); + } catch(e){}; + + // native matchesSelector function + + features.nativeMatchesSelector = root.matches || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector; + if (features.nativeMatchesSelector) try { + // if matchesSelector trows errors on incorrect sintaxes we can use it + features.nativeMatchesSelector.call(root, ':slick'); + features.nativeMatchesSelector = null; + } catch(e){}; + + } + + try { + root.slick_expando = 1; + delete root.slick_expando; + features.getUID = this.getUIDHTML; + } catch(e) { + features.getUID = this.getUIDXML; + } + + testRoot.removeChild(testNode); + testNode = selected = testRoot = null; + + // getAttribute + + features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){ + var method = this.attributeGetters[name]; + if (method) return method.call(node); + var attributeNode = node.getAttributeNode(name); + return (attributeNode) ? attributeNode.nodeValue : null; + } : function(node, name){ + var method = this.attributeGetters[name]; + return (method) ? method.call(node) : node.getAttribute(name); + }; + + // hasAttribute + + features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) { + return node.hasAttribute(attribute); + } : function(node, attribute) { + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }; + + // contains + // FIXME: Add specs: local.contains should be different for xml and html documents? + var nativeRootContains = root && this.isNativeCode(root.contains), + nativeDocumentContains = document && this.isNativeCode(document.contains); + + features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){ + return context.contains(node); + } : (nativeRootContains && !nativeDocumentContains) ? function(context, node){ + // IE8 does not have .contains on document. + return context === node || ((context === document) ? document.documentElement : context).contains(node); + } : (root && root.compareDocumentPosition) ? function(context, node){ + return context === node || !!(context.compareDocumentPosition(node) & 16); + } : function(context, node){ + if (node) do { + if (node === context) return true; + } while ((node = node.parentNode)); + return false; + }; + + // document order sorting + // credits to Sizzle (http://sizzlejs.com/) + + features.documentSorter = (root.compareDocumentPosition) ? function(a, b){ + if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0; + return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + } : ('sourceIndex' in root) ? function(a, b){ + if (!a.sourceIndex || !b.sourceIndex) return 0; + return a.sourceIndex - b.sourceIndex; + } : (document.createRange) ? function(a, b){ + if (!a.ownerDocument || !b.ownerDocument) return 0; + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + return aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + } : null ; + + root = null; + + for (feature in features){ + this[feature] = features[feature]; + } +}; + +// Main Method + +var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/, + reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/, + qsaFailExpCache = {}; + +local.search = function(context, expression, append, first){ + + var found = this.found = (first) ? null : (append || []); + + if (!context) return found; + else if (context.navigator) context = context.document; // Convert the node from a window to a document + else if (!context.nodeType) return found; + + // setup + + var parsed, i, + uniques = this.uniques = {}, + hasOthers = !!(append && append.length), + contextIsDocument = (context.nodeType == 9); + + if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context); + + // avoid duplicating items already in the append array + if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true; + + // expression checks + + if (typeof expression == 'string'){ // expression is a string + + /*<simple-selectors-override>*/ + var simpleSelector = expression.match(reSimpleSelector); + simpleSelectors: if (simpleSelector) { + + var symbol = simpleSelector[1], + name = simpleSelector[2], + node, nodes; + + if (!symbol){ + + if (name == '*' && this.brokenStarGEBTN) break simpleSelectors; + nodes = context.getElementsByTagName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + } else if (symbol == '#'){ + + if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors; + node = context.getElementById(name); + if (!node) return found; + if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors; + if (first) return node || null; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + + } else if (symbol == '.'){ + + if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors; + if (context.getElementsByClassName && !this.brokenGEBCN){ + nodes = context.getElementsByClassName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } else { + var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)'); + nodes = context.getElementsByTagName('*'); + for (i = 0; node = nodes[i++];){ + className = node.className; + if (!(className && matchClass.test(className))) continue; + if (first) return node; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } + + } + + if (hasOthers) this.sort(found); + return (first) ? null : found; + + } + /*</simple-selectors-override>*/ + + /*<query-selector-override>*/ + querySelector: if (context.querySelectorAll) { + + if (!this.isHTMLDocument + || qsaFailExpCache[expression] + //TODO: only skip when expression is actually mixed case + || this.brokenMixedCaseQSA + || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) + || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) + || (!contextIsDocument //Abort when !contextIsDocument and... + // there are multiple expressions in the selector + // since we currently only fix non-document rooted QSA for single expression selectors + && expression.indexOf(',') > -1 + ) + || Slick.disableQSA + ) break querySelector; + + var _expression = expression, _context = context; + if (!contextIsDocument){ + // non-document rooted QSA + // credits to Andrew Dupont + var currentId = _context.getAttribute('id'), slickid = 'slickid__'; + _context.setAttribute('id', slickid); + _expression = '#' + slickid + ' ' + _expression; + context = _context.parentNode; + } + + try { + if (first) return context.querySelector(_expression) || null; + else nodes = context.querySelectorAll(_expression); + } catch(e) { + qsaFailExpCache[expression] = 1; + break querySelector; + } finally { + if (!contextIsDocument){ + if (currentId) _context.setAttribute('id', currentId); + else _context.removeAttribute('id'); + context = _context; + } + } + + if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){ + if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node); + } else for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + if (hasOthers) this.sort(found); + return found; + + } + /*</query-selector-override>*/ + + parsed = this.Slick.parse(expression); + if (!parsed.length) return found; + } else if (expression == null){ // there is no expression + return found; + } else if (expression.Slick){ // expression is a parsed Slick object + parsed = expression; + } else if (this.contains(context.documentElement || context, expression)){ // expression is a node + (found) ? found.push(expression) : found = expression; + return found; + } else { // other junk + return found; + } + + /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ + + // cache elements for the nth selectors + + this.posNTH = {}; + this.posNTHLast = {}; + this.posNTHType = {}; + this.posNTHTypeLast = {}; + + /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ + + // if append is null and there is only a single selector with one expression use pushArray, else use pushUID + this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID; + + if (found == null) found = []; + + // default engine + + var j, m, n; + var combinator, tag, id, classList, classes, attributes, pseudos; + var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions; + + search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){ + + combinator = 'combinator:' + currentBit.combinator; + if (!this[combinator]) continue search; + + tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase(); + id = currentBit.id; + classList = currentBit.classList; + classes = currentBit.classes; + attributes = currentBit.attributes; + pseudos = currentBit.pseudos; + lastBit = (j === (currentExpression.length - 1)); + + this.bitUniques = {}; + + if (lastBit){ + this.uniques = uniques; + this.found = found; + } else { + this.uniques = {}; + this.found = []; + } + + if (j === 0){ + this[combinator](context, tag, id, classes, attributes, pseudos, classList); + if (first && lastBit && found.length) break search; + } else { + if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){ + this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + if (found.length) break search; + } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + } + + currentItems = this.found; + } + + // should sort if there are nodes in append and if you pass multiple expressions. + if (hasOthers || (parsed.expressions.length > 1)) this.sort(found); + + return (first) ? (found[0] || null) : found; +}; + +// Utils + +local.uidx = 1; +local.uidk = 'slick-uniqueid'; + +local.getUIDXML = function(node){ + var uid = node.getAttribute(this.uidk); + if (!uid){ + uid = this.uidx++; + node.setAttribute(this.uidk, uid); + } + return uid; +}; + +local.getUIDHTML = function(node){ + return node.uniqueNumber || (node.uniqueNumber = this.uidx++); +}; + +// sort based on the setDocument documentSorter method. + +local.sort = function(results){ + if (!this.documentSorter) return results; + results.sort(this.documentSorter); + return results; +}; + +/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ + +local.cacheNTH = {}; + +local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/; + +local.parseNTHArgument = function(argument){ + var parsed = argument.match(this.matchNTH); + if (!parsed) return false; + var special = parsed[2] || false; + var a = parsed[1] || 1; + if (a == '-') a = -1; + var b = +parsed[3] || 0; + parsed = + (special == 'n') ? {a: a, b: b} : + (special == 'odd') ? {a: 2, b: 1} : + (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a}; + + return (this.cacheNTH[argument] = parsed); +}; + +local.createNTHPseudo = function(child, sibling, positions, ofType){ + return function(node, argument){ + var uid = this.getUID(node); + if (!this[positions][uid]){ + var parent = node.parentNode; + if (!parent) return false; + var el = parent[child], count = 1; + if (ofType){ + var nodeName = node.nodeName; + do { + if (el.nodeName != nodeName) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } else { + do { + if (el.nodeType != 1) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } + } + argument = argument || 'n'; + var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument); + if (!parsed) return false; + var a = parsed.a, b = parsed.b, pos = this[positions][uid]; + if (a == 0) return b == pos; + if (a > 0){ + if (pos < b) return false; + } else { + if (b < pos) return false; + } + return ((pos - b) % a) == 0; + }; +}; + +/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ + +local.pushArray = function(node, tag, id, classes, attributes, pseudos){ + if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node); +}; + +local.pushUID = function(node, tag, id, classes, attributes, pseudos){ + var uid = this.getUID(node); + if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){ + this.uniques[uid] = true; + this.found.push(node); + } +}; + +local.matchNode = function(node, selector){ + if (this.isHTMLDocument && this.nativeMatchesSelector){ + try { + return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); + } catch(matchError) {} + } + + var parsed = this.Slick.parse(selector); + if (!parsed) return true; + + // simple (single) selectors + var expressions = parsed.expressions, simpleExpCounter = 0, i; + for (i = 0; (currentExpression = expressions[i]); i++){ + if (currentExpression.length == 1){ + var exp = currentExpression[0]; + if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; + simpleExpCounter++; + } + } + + if (simpleExpCounter == parsed.length) return false; + + var nodes = this.search(this.document, parsed), item; + for (i = 0; item = nodes[i++];){ + if (item === node) return true; + } + return false; +}; + +local.matchPseudo = function(node, name, argument){ + var pseudoName = 'pseudo:' + name; + if (this[pseudoName]) return this[pseudoName](node, argument); + var attribute = this.getAttribute(node, name); + return (argument) ? argument == attribute : !!attribute; +}; + +local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ + if (tag){ + var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase(); + if (tag == '*'){ + if (nodeName < '@') return false; // Fix for comment nodes and closed nodes + } else { + if (nodeName != tag) return false; + } + } + + if (id && node.getAttribute('id') != id) return false; + + var i, part, cls; + if (classes) for (i = classes.length; i--;){ + cls = this.getAttribute(node, 'class'); + if (!(cls && classes[i].regexp.test(cls))) return false; + } + if (attributes) for (i = attributes.length; i--;){ + part = attributes[i]; + if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false; + } + if (pseudos) for (i = pseudos.length; i--;){ + part = pseudos[i]; + if (!this.matchPseudo(node, part.key, part.value)) return false; + } + return true; +}; + +var combinators = { + + ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level + + var i, item, children; + + if (this.isHTMLDocument){ + getById: if (id){ + item = this.document.getElementById(id); + if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){ + // all[id] returns all the elements with that name or id inside node + // if theres just one it will return the element, else it will be a collection + children = node.all[id]; + if (!children) return; + if (!children[0]) children = [children]; + for (i = 0; item = children[i++];){ + var idNode = item.getAttributeNode('id'); + if (idNode && idNode.nodeValue == id){ + this.push(item, tag, null, classes, attributes, pseudos); + break; + } + } + return; + } + if (!item){ + // if the context is in the dom we return, else we will try GEBTN, breaking the getById label + if (this.contains(this.root, node)) return; + else break getById; + } else if (this.document !== node && !this.contains(node, item)) return; + this.push(item, tag, null, classes, attributes, pseudos); + return; + } + getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){ + children = node.getElementsByClassName(classList.join(' ')); + if (!(children && children.length)) break getByClass; + for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos); + return; + } + } + getByTag: { + children = node.getElementsByTagName(tag); + if (!(children && children.length)) break getByTag; + if (!this.brokenStarGEBTN) tag = null; + for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos); + } + }, + + '>': function(node, tag, id, classes, attributes, pseudos){ // direct children + if ((node = node.firstChild)) do { + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + } while ((node = node.nextSibling)); + }, + + '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling + while ((node = node.nextSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '^': function(node, tag, id, classes, attributes, pseudos){ // first child + node = node.firstChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings + while ((node = node.nextSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + }, + + '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling + this['combinator:+'](node, tag, id, classes, attributes, pseudos); + this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + }, + + '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings + this['combinator:~'](node, tag, id, classes, attributes, pseudos); + this['combinator:!~'](node, tag, id, classes, attributes, pseudos); + }, + + '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document + while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level) + node = node.parentNode; + if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling + while ((node = node.previousSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '!^': function(node, tag, id, classes, attributes, pseudos){ // last child + node = node.lastChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings + while ((node = node.previousSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + } + +}; + +for (var c in combinators) local['combinator:' + c] = combinators[c]; + +var pseudos = { + + /*<pseudo-selectors>*/ + + 'empty': function(node){ + var child = node.firstChild; + return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length; + }, + + 'not': function(node, expression){ + return !this.matchNode(node, expression); + }, + + 'contains': function(node, text){ + return (node.innerText || node.textContent || '').indexOf(text) > -1; + }, + + 'first-child': function(node){ + while ((node = node.previousSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'last-child': function(node){ + while ((node = node.nextSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'only-child': function(node){ + var prev = node; + while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeType == 1) return false; + return true; + }, + + /*<nth-pseudo-selectors>*/ + + 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'), + + 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'), + + 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true), + + 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), + + 'index': function(node, index){ + return this['pseudo:nth-child'](node, '' + (index + 1)); + }, + + 'even': function(node){ + return this['pseudo:nth-child'](node, '2n'); + }, + + 'odd': function(node){ + return this['pseudo:nth-child'](node, '2n+1'); + }, + + /*</nth-pseudo-selectors>*/ + + /*<of-type-pseudo-selectors>*/ + + 'first-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'last-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'only-of-type': function(node){ + var prev = node, nodeName = node.nodeName; + while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false; + return true; + }, + + /*</of-type-pseudo-selectors>*/ + + // custom pseudos + + 'enabled': function(node){ + return !node.disabled; + }, + + 'disabled': function(node){ + return node.disabled; + }, + + 'checked': function(node){ + return node.checked || node.selected; + }, + + 'focus': function(node){ + return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex')); + }, + + 'root': function(node){ + return (node === this.root); + }, + + 'selected': function(node){ + return node.selected; + } + + /*</pseudo-selectors>*/ +}; + +for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; + +// attributes methods + +var attributeGetters = local.attributeGetters = { + + 'for': function(){ + return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); + }, + + 'href': function(){ + return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href'); + }, + + 'style': function(){ + return (this.style) ? this.style.cssText : this.getAttribute('style'); + }, + + 'tabindex': function(){ + var attributeNode = this.getAttributeNode('tabindex'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; + }, + + 'type': function(){ + return this.getAttribute('type'); + }, + + 'maxlength': function(){ + var attributeNode = this.getAttributeNode('maxLength'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; + } + +}; + +attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength; + +// Slick + +var Slick = local.Slick = (this.Slick || {}); + +Slick.version = '1.1.7'; + +// Slick finder + +Slick.search = function(context, expression, append){ + return local.search(context, expression, append); +}; + +Slick.find = function(context, expression){ + return local.search(context, expression, null, true); +}; + +// Slick containment checker + +Slick.contains = function(container, node){ + local.setDocument(container); + return local.contains(container, node); +}; + +// Slick attribute getter + +Slick.getAttribute = function(node, name){ + local.setDocument(node); + return local.getAttribute(node, name); +}; + +Slick.hasAttribute = function(node, name){ + local.setDocument(node); + return local.hasAttribute(node, name); +}; + +// Slick matcher + +Slick.match = function(node, selector){ + if (!(node && selector)) return false; + if (!selector || selector === node) return true; + local.setDocument(node); + return local.matchNode(node, selector); +}; + +// Slick attribute accessor + +Slick.defineAttributeGetter = function(name, fn){ + local.attributeGetters[name] = fn; + return this; +}; + +Slick.lookupAttributeGetter = function(name){ + return local.attributeGetters[name]; +}; + +// Slick pseudo accessor + +Slick.definePseudo = function(name, fn){ + local['pseudo:' + name] = function(node, argument){ + return fn.call(node, argument); + }; + return this; +}; + +Slick.lookupPseudo = function(name){ + var pseudo = local['pseudo:' + name]; + if (pseudo) return function(argument){ + return pseudo.call(this, argument); + }; + return null; +}; + +// Slick overrides accessor + +Slick.override = function(regexp, fn){ + local.override(regexp, fn); + return this; +}; + +Slick.isXML = local.isXML; + +Slick.uidOf = function(node){ + return local.getUIDHTML(node); +}; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); + + +/* +--- + +name: Element + +description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. + +license: MIT-style license. + +requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder] + +provides: [Element, Elements, $, $$, IFrame, Selectors] + +... +*/ + +var Element = this.Element = function(tag, props){ + var konstructor = Element.Constructors[tag]; + if (konstructor) return konstructor(props); + if (typeof tag != 'string') return document.id(tag).set(props); + + if (!props) props = {}; + + if (!(/^[\w-]+$/).test(tag)){ + var parsed = Slick.parse(tag).expressions[0][0]; + tag = (parsed.tag == '*') ? 'div' : parsed.tag; + if (parsed.id && props.id == null) props.id = parsed.id; + + var attributes = parsed.attributes; + if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){ + attr = attributes[i]; + if (props[attr.key] != null) continue; + + if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; + else if (!attr.value && !attr.operator) props[attr.key] = true; + } + + if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); + } + + return document.newElement(tag, props); +}; + + +if (Browser.Element){ + Element.prototype = Browser.Element.prototype; + // IE8 and IE9 require the wrapping. + Element.prototype._fireEvent = (function(fireEvent){ + return function(type, event){ + return fireEvent.call(this, type, event); + }; + })(Element.prototype.fireEvent); +} + +new Type('Element', Element).mirror(function(name){ + if (Array.prototype[name]) return; + + var obj = {}; + obj[name] = function(){ + var results = [], args = arguments, elements = true; + for (var i = 0, l = this.length; i < l; i++){ + var element = this[i], result = results[i] = element[name].apply(element, args); + elements = (elements && typeOf(result) == 'element'); + } + return (elements) ? new Elements(results) : results; + }; + + Elements.implement(obj); +}); + +if (!Browser.Element){ + Element.parent = Object; + + Element.Prototype = { + '$constructor': Element, + '$family': Function.from('element').hide() + }; + + Element.mirror(function(name, method){ + Element.Prototype[name] = method; + }); +} + +Element.Constructors = {}; + + + +var IFrame = new Type('IFrame', function(){ + var params = Array.link(arguments, { + properties: Type.isObject, + iframe: function(obj){ + return (obj != null); + } + }); + + var props = params.properties || {}, iframe; + if (params.iframe) iframe = document.id(params.iframe); + var onload = props.onload || function(){}; + delete props.onload; + props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); + iframe = new Element(iframe || 'iframe', props); + + var onLoad = function(){ + onload.call(iframe.contentWindow); + }; + + if (window.frames[props.id]) onLoad(); + else iframe.addListener('load', onLoad); + return iframe; +}); + +var Elements = this.Elements = function(nodes){ + if (nodes && nodes.length){ + var uniques = {}, node; + for (var i = 0; node = nodes[i++];){ + var uid = Slick.uidOf(node); + if (!uniques[uid]){ + uniques[uid] = true; + this.push(node); + } + } + } +}; + +Elements.prototype = {length: 0}; +Elements.parent = Array; + +new Type('Elements', Elements).implement({ + + filter: function(filter, bind){ + if (!filter) return this; + return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ + return item.match(filter); + } : filter, bind)); + }.protect(), + + push: function(){ + var length = this.length; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) this[length++] = item; + } + return (this.length = length); + }.protect(), + + unshift: function(){ + var items = []; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) items.push(item); + } + return Array.prototype.unshift.apply(this, items); + }.protect(), + + concat: function(){ + var newElements = new Elements(this); + for (var i = 0, l = arguments.length; i < l; i++){ + var item = arguments[i]; + if (Type.isEnumerable(item)) newElements.append(item); + else newElements.push(item); + } + return newElements; + }.protect(), + + append: function(collection){ + for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); + return this; + }.protect(), + + empty: function(){ + while (this.length) delete this[--this.length]; + return this; + }.protect() + +}); + + + +(function(){ + +// FF, IE +var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; + +splice.call(object, 1, 1); +if (object[1] == 1) Elements.implement('splice', function(){ + var length = this.length; + var result = splice.apply(this, arguments); + while (length >= this.length) delete this[length--]; + return result; +}.protect()); + +Array.forEachMethod(function(method, name){ + Elements.implement(name, method); +}); + +Array.mirror(Elements); + +/*<ltIE8>*/ +var createElementAcceptsHTML; +try { + createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x'); +} catch (e){} + +var escapeQuotes = function(html){ + return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); +}; +/*</ltIE8>*/ + +Document.implement({ + + newElement: function(tag, props){ + if (props && props.checked != null) props.defaultChecked = props.checked; + /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8 + if (createElementAcceptsHTML && props){ + tag = '<' + tag; + if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; + if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; + tag += '>'; + delete props.name; + delete props.type; + } + /*</ltIE8>*/ + return this.id(this.createElement(tag)).set(props); + } + +}); + +})(); + +(function(){ + +Slick.uidOf(window); +Slick.uidOf(document); + +Document.implement({ + + newTextNode: function(text){ + return this.createTextNode(text); + }, + + getDocument: function(){ + return this; + }, + + getWindow: function(){ + return this.window; + }, + + id: (function(){ + + var types = { + + string: function(id, nocash, doc){ + id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); + return (id) ? types.element(id, nocash) : null; + }, + + element: function(el, nocash){ + Slick.uidOf(el); + if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ + var fireEvent = el.fireEvent; + // wrapping needed in IE7, or else crash + el._fireEvent = function(type, event){ + return fireEvent(type, event); + }; + Object.append(el, Element.Prototype); + } + return el; + }, + + object: function(obj, nocash, doc){ + if (obj.toElement) return types.element(obj.toElement(doc), nocash); + return null; + } + + }; + + types.textnode = types.whitespace = types.window = types.document = function(zero){ + return zero; + }; + + return function(el, nocash, doc){ + if (el && el.$family && el.uniqueNumber) return el; + var type = typeOf(el); + return (types[type]) ? types[type](el, nocash, doc || document) : null; + }; + + })() + +}); + +if (window.$ == null) Window.implement('$', function(el, nc){ + return document.id(el, nc, this.document); +}); + +Window.implement({ + + getDocument: function(){ + return this.document; + }, + + getWindow: function(){ + return this; + } + +}); + +[Document, Element].invoke('implement', { + + getElements: function(expression){ + return Slick.search(this, expression, new Elements); + }, + + getElement: function(expression){ + return document.id(Slick.find(this, expression)); + } + +}); + +var contains = {contains: function(element){ + return Slick.contains(this, element); +}}; + +if (!document.contains) Document.implement(contains); +if (!document.createElement('div').contains) Element.implement(contains); + + + +// tree walking + +var injectCombinator = function(expression, combinator){ + if (!expression) return combinator; + + expression = Object.clone(Slick.parse(expression)); + + var expressions = expression.expressions; + for (var i = expressions.length; i--;) + expressions[i][0].combinator = combinator; + + return expression; +}; + +Object.forEach({ + getNext: '~', + getPrevious: '!~', + getParent: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElement(injectCombinator(expression, combinator)); + }); +}); + +Object.forEach({ + getAllNext: '~', + getAllPrevious: '!~', + getSiblings: '~~', + getChildren: '>', + getParents: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElements(injectCombinator(expression, combinator)); + }); +}); + +Element.implement({ + + getFirst: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); + }, + + getLast: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); + }, + + getWindow: function(){ + return this.ownerDocument.window; + }, + + getDocument: function(){ + return this.ownerDocument; + }, + + getElementById: function(id){ + return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); + }, + + match: function(expression){ + return !expression || Slick.match(this, expression); + } + +}); + + + +if (window.$$ == null) Window.implement('$$', function(selector){ + if (arguments.length == 1){ + if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); + else if (Type.isEnumerable(selector)) return new Elements(selector); + } + return new Elements(arguments); +}); + +// Inserters + +var inserters = { + + before: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element); + }, + + after: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element.nextSibling); + }, + + bottom: function(context, element){ + element.appendChild(context); + }, + + top: function(context, element){ + element.insertBefore(context, element.firstChild); + } + +}; + +inserters.inside = inserters.bottom; + + + +// getProperty / setProperty + +var propertyGetters = {}, propertySetters = {}; + +// properties + +var properties = {}; +Array.forEach([ + 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', + 'frameBorder', 'rowSpan', 'tabIndex', 'useMap' +], function(property){ + properties[property.toLowerCase()] = property; +}); + +properties.html = 'innerHTML'; +properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent'; + +Object.forEach(properties, function(real, key){ + propertySetters[key] = function(node, value){ + node[real] = value; + }; + propertyGetters[key] = function(node){ + return node[real]; + }; +}); + +// Booleans + +var bools = [ + 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', + 'disabled', 'readOnly', 'multiple', 'selected', 'noresize', + 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay', + 'loop' +]; + +var booleans = {}; +Array.forEach(bools, function(bool){ + var lower = bool.toLowerCase(); + booleans[lower] = bool; + propertySetters[lower] = function(node, value){ + node[bool] = !!value; + }; + propertyGetters[lower] = function(node){ + return !!node[bool]; + }; +}); + +// Special cases + +Object.append(propertySetters, { + + 'class': function(node, value){ + ('className' in node) ? node.className = (value || '') : node.setAttribute('class', value); + }, + + 'for': function(node, value){ + ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value); + }, + + 'style': function(node, value){ + (node.style) ? node.style.cssText = value : node.setAttribute('style', value); + }, + + 'value': function(node, value){ + node.value = (value != null) ? value : ''; + } + +}); + +propertyGetters['class'] = function(node){ + return ('className' in node) ? node.className || null : node.getAttribute('class'); +}; + +/* <webkit> */ +var el = document.createElement('button'); +// IE sets type as readonly and throws +try { el.type = 'button'; } catch(e){} +if (el.type != 'button') propertySetters.type = function(node, value){ + node.setAttribute('type', value); +}; +el = null; +/* </webkit> */ + +/*<IE>*/ +var input = document.createElement('input'); +input.value = 't'; +input.type = 'submit'; +if (input.value != 't') propertySetters.type = function(node, type){ + var value = node.value; + node.type = type; + node.value = value; +}; +input = null; +/*</IE>*/ + +/* getProperty, setProperty */ + +/* <ltIE9> */ +var pollutesGetAttribute = (function(div){ + div.random = 'attribute'; + return (div.getAttribute('random') == 'attribute'); +})(document.createElement('div')); + +var hasCloneBug = (function(test){ + test.innerHTML = '<object><param name="should_fix" value="the unknown"></object>'; + return test.cloneNode(true).firstChild.childNodes.length != 1; +})(document.createElement('div')); +/* </ltIE9> */ + +var hasClassList = !!document.createElement('div').classList; + +var classes = function(className){ + var classNames = (className || '').clean().split(" "), uniques = {}; + return classNames.filter(function(className){ + if (className !== "" && !uniques[className]) return uniques[className] = className; + }); +}; + +var addToClassList = function(name){ + this.classList.add(name); +}; + +var removeFromClassList = function(name){ + this.classList.remove(name); +}; + +Element.implement({ + + setProperty: function(name, value){ + var setter = propertySetters[name.toLowerCase()]; + if (setter){ + setter(this, value); + } else { + /* <ltIE9> */ + var attributeWhiteList; + if (pollutesGetAttribute) attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + /* </ltIE9> */ + + if (value == null){ + this.removeAttribute(name); + /* <ltIE9> */ + if (pollutesGetAttribute) delete attributeWhiteList[name]; + /* </ltIE9> */ + } else { + this.setAttribute(name, '' + value); + /* <ltIE9> */ + if (pollutesGetAttribute) attributeWhiteList[name] = true; + /* </ltIE9> */ + } + } + return this; + }, + + setProperties: function(attributes){ + for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); + return this; + }, + + getProperty: function(name){ + var getter = propertyGetters[name.toLowerCase()]; + if (getter) return getter(this); + /* <ltIE9> */ + if (pollutesGetAttribute){ + var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + if (!attr) return null; + if (attr.expando && !attributeWhiteList[name]){ + var outer = this.outerHTML; + // segment by the opening tag and find mention of attribute name + if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null; + attributeWhiteList[name] = true; + } + } + /* </ltIE9> */ + var result = Slick.getAttribute(this, name); + return (!result && !Slick.hasAttribute(this, name)) ? null : result; + }, + + getProperties: function(){ + var args = Array.from(arguments); + return args.map(this.getProperty, this).associate(args); + }, + + removeProperty: function(name){ + return this.setProperty(name, null); + }, + + removeProperties: function(){ + Array.each(arguments, this.removeProperty, this); + return this; + }, + + set: function(prop, value){ + var property = Element.Properties[prop]; + (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); + }.overloadSetter(), + + get: function(prop){ + var property = Element.Properties[prop]; + return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); + }.overloadGetter(), + + erase: function(prop){ + var property = Element.Properties[prop]; + (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); + return this; + }, + + hasClass: hasClassList ? function(className){ + return this.classList.contains(className); + } : function(className){ + return this.className.clean().contains(className, ' '); + }, + + addClass: hasClassList ? function(className){ + classes(className).forEach(addToClassList, this); + return this; + } : function(className){ + this.className = classes(className + ' ' + this.className).join(' '); + return this; + }, + + removeClass: hasClassList ? function(className){ + classes(className).forEach(removeFromClassList, this); + return this; + } : function(className){ + var classNames = classes(this.className); + classes(className).forEach(classNames.erase, classNames); + this.className = classNames.join(' '); + return this; + }, + + toggleClass: function(className, force){ + if (force == null) force = !this.hasClass(className); + return (force) ? this.addClass(className) : this.removeClass(className); + }, + + adopt: function(){ + var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; + if (length > 1) parent = fragment = document.createDocumentFragment(); + + for (var i = 0; i < length; i++){ + var element = document.id(elements[i], true); + if (element) parent.appendChild(element); + } + + if (fragment) this.appendChild(fragment); + + return this; + }, + + appendText: function(text, where){ + return this.grab(this.getDocument().newTextNode(text), where); + }, + + grab: function(el, where){ + inserters[where || 'bottom'](document.id(el, true), this); + return this; + }, + + inject: function(el, where){ + inserters[where || 'bottom'](this, document.id(el, true)); + return this; + }, + + replaces: function(el){ + el = document.id(el, true); + el.parentNode.replaceChild(this, el); + return this; + }, + + wraps: function(el, where){ + el = document.id(el, true); + return this.replaces(el).grab(el, where); + }, + + getSelected: function(){ + this.selectedIndex; // Safari 3.2.1 + return new Elements(Array.from(this.options).filter(function(option){ + return option.selected; + })); + }, + + toQueryString: function(){ + var queryString = []; + this.getElements('input, select, textarea').each(function(el){ + var type = el.type; + if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; + + var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ + // IE + return document.id(opt).get('value'); + }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); + + Array.from(value).each(function(val){ + if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); + }); + }); + return queryString.join('&'); + } + +}); + + +// appendHTML + +var appendInserters = { + before: 'beforeBegin', + after: 'afterEnd', + bottom: 'beforeEnd', + top: 'afterBegin', + inside: 'beforeEnd' +}; + +Element.implement('appendHTML', ('insertAdjacentHTML' in document.createElement('div')) ? function(html, where){ + this.insertAdjacentHTML(appendInserters[where || 'bottom'], html); + return this; +} : function(html, where){ + var temp = new Element('div', {html: html}), + children = temp.childNodes, + fragment = temp.firstChild; + + if (!fragment) return this; + if (children.length > 1){ + fragment = document.createDocumentFragment(); + for (var i = 0, l = children.length; i < l; i++){ + fragment.appendChild(children[i]); + } + } + + inserters[where || 'bottom'](fragment, this); + return this; +}); + +var collected = {}, storage = {}; + +var get = function(uid){ + return (storage[uid] || (storage[uid] = {})); +}; + +var clean = function(item){ + var uid = item.uniqueNumber; + if (item.removeEvents) item.removeEvents(); + if (item.clearAttributes) item.clearAttributes(); + if (uid != null){ + delete collected[uid]; + delete storage[uid]; + } + return item; +}; + +var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; + +Element.implement({ + + destroy: function(){ + var children = clean(this).getElementsByTagName('*'); + Array.each(children, clean); + Element.dispose(this); + return null; + }, + + empty: function(){ + Array.from(this.childNodes).each(Element.dispose); + return this; + }, + + dispose: function(){ + return (this.parentNode) ? this.parentNode.removeChild(this) : this; + }, + + clone: function(contents, keepid){ + contents = contents !== false; + var clone = this.cloneNode(contents), ce = [clone], te = [this], i; + + if (contents){ + ce.append(Array.from(clone.getElementsByTagName('*'))); + te.append(Array.from(this.getElementsByTagName('*'))); + } + + for (i = ce.length; i--;){ + var node = ce[i], element = te[i]; + if (!keepid) node.removeAttribute('id'); + /*<ltIE9>*/ + if (node.clearAttributes){ + node.clearAttributes(); + node.mergeAttributes(element); + node.removeAttribute('uniqueNumber'); + if (node.options){ + var no = node.options, eo = element.options; + for (var j = no.length; j--;) no[j].selected = eo[j].selected; + } + } + /*</ltIE9>*/ + var prop = formProps[element.tagName.toLowerCase()]; + if (prop && element[prop]) node[prop] = element[prop]; + } + + /*<ltIE9>*/ + if (hasCloneBug){ + var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); + for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; + } + /*</ltIE9>*/ + return document.id(clone); + } + +}); + +[Element, Window, Document].invoke('implement', { + + addListener: function(type, fn){ + if (window.attachEvent && !window.addEventListener){ + collected[Slick.uidOf(this)] = this; + } + if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); + else this.attachEvent('on' + type, fn); + return this; + }, + + removeListener: function(type, fn){ + if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); + else this.detachEvent('on' + type, fn); + return this; + }, + + retrieve: function(property, dflt){ + var storage = get(Slick.uidOf(this)), prop = storage[property]; + if (dflt != null && prop == null) prop = storage[property] = dflt; + return prop != null ? prop : null; + }, + + store: function(property, value){ + var storage = get(Slick.uidOf(this)); + storage[property] = value; + return this; + }, + + eliminate: function(property){ + var storage = get(Slick.uidOf(this)); + delete storage[property]; + return this; + } + +}); + +/*<ltIE9>*/ +if (window.attachEvent && !window.addEventListener){ + var gc = function(){ + Object.each(collected, clean); + if (window.CollectGarbage) CollectGarbage(); + window.removeListener('unload', gc); + } + window.addListener('unload', gc); +} +/*</ltIE9>*/ + +Element.Properties = {}; + + + +Element.Properties.style = { + + set: function(style){ + this.style.cssText = style; + }, + + get: function(){ + return this.style.cssText; + }, + + erase: function(){ + this.style.cssText = ''; + } + +}; + +Element.Properties.tag = { + + get: function(){ + return this.tagName.toLowerCase(); + } + +}; + +Element.Properties.html = { + + set: function(html){ + if (html == null) html = ''; + else if (typeOf(html) == 'array') html = html.join(''); + this.innerHTML = html; + }, + + erase: function(){ + this.innerHTML = ''; + } + +}; + +var supportsHTML5Elements = true, supportsTableInnerHTML = true, supportsTRInnerHTML = true; + +/*<ltIE9>*/ +// technique by jdbarlett - http://jdbartlett.com/innershiv/ +var div = document.createElement('div'); +div.innerHTML = '<nav></nav>'; +supportsHTML5Elements = (div.childNodes.length == 1); +if (!supportsHTML5Elements){ + var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), + fragment = document.createDocumentFragment(), l = tags.length; + while (l--) fragment.createElement(tags[l]); +} +div = null; +/*</ltIE9>*/ + +/*<IE>*/ +supportsTableInnerHTML = Function.attempt(function(){ + var table = document.createElement('table'); + table.innerHTML = '<tr><td></td></tr>'; + return true; +}); + +/*<ltFF4>*/ +var tr = document.createElement('tr'), html = '<td></td>'; +tr.innerHTML = html; +supportsTRInnerHTML = (tr.innerHTML == html); +tr = null; +/*</ltFF4>*/ + +if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){ + + Element.Properties.html.set = (function(set){ + + var translations = { + table: [1, '<table>', '</table>'], + select: [1, '<select>', '</select>'], + tbody: [2, '<table><tbody>', '</tbody></table>'], + tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] + }; + + translations.thead = translations.tfoot = translations.tbody; + + return function(html){ + var wrap = translations[this.get('tag')]; + if (!wrap && !supportsHTML5Elements) wrap = [0, '', '']; + if (!wrap) return set.call(this, html); + + var level = wrap[0], wrapper = document.createElement('div'), target = wrapper; + if (!supportsHTML5Elements) fragment.appendChild(wrapper); + wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join(''); + while (level--) target = target.firstChild; + this.empty().adopt(target.childNodes); + if (!supportsHTML5Elements) fragment.removeChild(wrapper); + wrapper = null; + }; + + })(Element.Properties.html.set); +} +/*</IE>*/ + +/*<ltIE9>*/ +var testForm = document.createElement('form'); +testForm.innerHTML = '<select><option>s</option></select>'; + +if (testForm.firstChild.value != 's') Element.Properties.value = { + + set: function(value){ + var tag = this.get('tag'); + if (tag != 'select') return this.setProperty('value', value); + var options = this.getElements('option'); + value = String(value); + for (var i = 0; i < options.length; i++){ + var option = options[i], + attr = option.getAttributeNode('value'), + optionValue = (attr && attr.specified) ? option.value : option.get('text'); + if (optionValue === value) return option.selected = true; + } + }, + + get: function(){ + var option = this, tag = option.get('tag'); + + if (tag != 'select' && tag != 'option') return this.getProperty('value'); + + if (tag == 'select' && !(option = option.getSelected()[0])) return ''; + + var attr = option.getAttributeNode('value'); + return (attr && attr.specified) ? option.value : option.get('text'); + } + +}; +testForm = null; +/*</ltIE9>*/ + +/*<IE>*/ +if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = { + set: function(id){ + this.id = this.getAttributeNode('id').value = id; + }, + get: function(){ + return this.id || null; + }, + erase: function(){ + this.id = this.getAttributeNode('id').value = ''; + } +}; +/*</IE>*/ + +})(); + + +/* +--- + +name: Element.Style + +description: Contains methods for interacting with the styles of Elements in a fashionable way. + +license: MIT-style license. + +requires: Element + +provides: Element.Style + +... +*/ + +(function(){ + +var html = document.html, el; + +//<ltIE9> +// Check for oldIE, which does not remove styles when they're set to null +el = document.createElement('div'); +el.style.color = 'red'; +el.style.color = null; +var doesNotRemoveStyles = el.style.color == 'red'; + +// check for oldIE, which returns border* shorthand styles in the wrong order (color-width-style instead of width-style-color) +var border = '1px solid #123abc'; +el.style.border = border; +var returnsBordersInWrongOrder = el.style.border != border; +el = null; +//</ltIE9> + +var hasGetComputedStyle = !!window.getComputedStyle; + +Element.Properties.styles = {set: function(styles){ + this.setStyles(styles); +}}; + +var hasOpacity = (html.style.opacity != null), + hasFilter = (html.style.filter != null), + reAlpha = /alpha\(opacity=([\d.]+)\)/i; + +var setVisibility = function(element, opacity){ + element.store('$opacity', opacity); + element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden'; +}; + +//<ltIE9> +var setFilter = function(element, regexp, value){ + var style = element.style, + filter = style.filter || element.getComputedStyle('filter') || ''; + style.filter = (regexp.test(filter) ? filter.replace(regexp, value) : filter + ' ' + value).trim(); + if (!style.filter) style.removeAttribute('filter'); +}; +//</ltIE9> + +var setOpacity = (hasOpacity ? function(element, opacity){ + element.style.opacity = opacity; +} : (hasFilter ? function(element, opacity){ + if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; + if (opacity == null || opacity == 1){ + setFilter(element, reAlpha, ''); + if (opacity == 1 && getOpacity(element) != 1) setFilter(element, reAlpha, 'alpha(opacity=100)'); + } else { + setFilter(element, reAlpha, 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')'); + } +} : setVisibility)); + +var getOpacity = (hasOpacity ? function(element){ + var opacity = element.style.opacity || element.getComputedStyle('opacity'); + return (opacity == '') ? 1 : opacity.toFloat(); +} : (hasFilter ? function(element){ + var filter = (element.style.filter || element.getComputedStyle('filter')), + opacity; + if (filter) opacity = filter.match(reAlpha); + return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); +} : function(element){ + var opacity = element.retrieve('$opacity'); + if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1); + return opacity; +})); + +var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat', + namedPositions = {left: '0%', top: '0%', center: '50%', right: '100%', bottom: '100%'}, + hasBackgroundPositionXY = (html.style.backgroundPositionX != null); + +//<ltIE9> +var removeStyle = function(style, property){ + if (property == 'backgroundPosition'){ + style.removeAttribute(property + 'X'); + property += 'Y'; + } + style.removeAttribute(property); +}; +//</ltIE9> + +Element.implement({ + + getComputedStyle: function(property){ + if (!hasGetComputedStyle && this.currentStyle) return this.currentStyle[property.camelCase()]; + var defaultView = Element.getDocument(this).defaultView, + computed = defaultView ? defaultView.getComputedStyle(this, null) : null; + return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : ''; + }, + + setStyle: function(property, value){ + if (property == 'opacity'){ + if (value != null) value = parseFloat(value); + setOpacity(this, value); + return this; + } + property = (property == 'float' ? floatName : property).camelCase(); + if (typeOf(value) != 'string'){ + var map = (Element.Styles[property] || '@').split(' '); + value = Array.from(value).map(function(val, i){ + if (!map[i]) return ''; + return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; + }).join(' '); + } else if (value == String(Number(value))){ + value = Math.round(value); + } + this.style[property] = value; + //<ltIE9> + if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){ + removeStyle(this.style, property); + } + //</ltIE9> + return this; + }, + + getStyle: function(property){ + if (property == 'opacity') return getOpacity(this); + property = (property == 'float' ? floatName : property).camelCase(); + var result = this.style[property]; + if (!result || property == 'zIndex'){ + if (Element.ShortStyles.hasOwnProperty(property)){ + result = []; + for (var s in Element.ShortStyles[property]) result.push(this.getStyle(s)); + return result.join(' '); + } + result = this.getComputedStyle(property); + } + if (hasBackgroundPositionXY && /^backgroundPosition[XY]?$/.test(property)){ + return result.replace(/(top|right|bottom|left)/g, function(position){ + return namedPositions[position]; + }) || '0px'; + } + if (!result && property == 'backgroundPosition') return '0px 0px'; + if (result){ + result = String(result); + var color = result.match(/rgba?\([\d\s,]+\)/); + if (color) result = result.replace(color[0], color[0].rgbToHex()); + } + if (!hasGetComputedStyle && !this.style[property]){ + if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){ + var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; + values.each(function(value){ + size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); + }, this); + return this['offset' + property.capitalize()] - size + 'px'; + } + if ((/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){ + return '0px'; + } + } + //<ltIE9> + if (returnsBordersInWrongOrder && /^border(Top|Right|Bottom|Left)?$/.test(property) && /^#/.test(result)){ + return result.replace(/^(.+)\s(.+)\s(.+)$/, '$2 $3 $1'); + } + //</ltIE9> + return result; + }, + + setStyles: function(styles){ + for (var style in styles) this.setStyle(style, styles[style]); + return this; + }, + + getStyles: function(){ + var result = {}; + Array.flatten(arguments).each(function(key){ + result[key] = this.getStyle(key); + }, this); + return result; + } + +}); + +Element.Styles = { + left: '@px', top: '@px', bottom: '@px', right: '@px', + width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', + backgroundColor: 'rgb(@, @, @)', backgroundSize: '@px', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', + fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', + margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', + borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', + zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' +}; + + + + + +Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; + +['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ + var Short = Element.ShortStyles; + var All = Element.Styles; + ['margin', 'padding'].each(function(style){ + var sd = style + direction; + Short[style][sd] = All[sd] = '@px'; + }); + var bd = 'border' + direction; + Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; + var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; + Short[bd] = {}; + Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; + Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; + Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; +}); + +if (hasBackgroundPositionXY) Element.ShortStyles.backgroundPosition = {backgroundPositionX: '@', backgroundPositionY: '@'}; +})(); + + +/* +--- + +name: Element.Event + +description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary. + +license: MIT-style license. + +requires: [Element, Event] + +provides: Element.Event + +... +*/ + +(function(){ + +Element.Properties.events = {set: function(events){ + this.addEvents(events); +}}; + +[Element, Window, Document].invoke('implement', { + + addEvent: function(type, fn){ + var events = this.retrieve('events', {}); + if (!events[type]) events[type] = {keys: [], values: []}; + if (events[type].keys.contains(fn)) return this; + events[type].keys.push(fn); + var realType = type, + custom = Element.Events[type], + condition = fn, + self = this; + if (custom){ + if (custom.onAdd) custom.onAdd.call(this, fn, type); + if (custom.condition){ + condition = function(event){ + if (custom.condition.call(this, event, type)) return fn.call(this, event); + return true; + }; + } + if (custom.base) realType = Function.from(custom.base).call(this, type); + } + var defn = function(){ + return fn.call(self); + }; + var nativeEvent = Element.NativeEvents[realType]; + if (nativeEvent){ + if (nativeEvent == 2){ + defn = function(event){ + event = new DOMEvent(event, self.getWindow()); + if (condition.call(self, event) === false) event.stop(); + }; + } + this.addListener(realType, defn, arguments[2]); + } + events[type].values.push(defn); + return this; + }, + + removeEvent: function(type, fn){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + var list = events[type]; + var index = list.keys.indexOf(fn); + if (index == -1) return this; + var value = list.values[index]; + delete list.keys[index]; + delete list.values[index]; + var custom = Element.Events[type]; + if (custom){ + if (custom.onRemove) custom.onRemove.call(this, fn, type); + if (custom.base) type = Function.from(custom.base).call(this, type); + } + return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; + }, + + addEvents: function(events){ + for (var event in events) this.addEvent(event, events[event]); + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + var attached = this.retrieve('events'); + if (!attached) return this; + if (!events){ + for (type in attached) this.removeEvents(type); + this.eliminate('events'); + } else if (attached[events]){ + attached[events].keys.each(function(fn){ + this.removeEvent(events, fn); + }, this); + delete attached[events]; + } + return this; + }, + + fireEvent: function(type, args, delay){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + args = Array.from(args); + + events[type].keys.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + cloneEvents: function(from, type){ + from = document.id(from); + var events = from.retrieve('events'); + if (!events) return this; + if (!type){ + for (var eventType in events) this.cloneEvents(from, eventType); + } else if (events[type]){ + events[type].keys.each(function(fn){ + this.addEvent(type, fn); + }, this); + } + return this; + } + +}); + +Element.NativeEvents = { + click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons + mousewheel: 2, DOMMouseScroll: 2, //mouse wheel + mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement + keydown: 2, keypress: 2, keyup: 2, //keyboard + orientationchange: 2, // mobile + touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch + gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture + focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements + load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window + hashchange: 1, popstate: 2, // history + error: 1, abort: 1, scroll: 1 //misc +}; + +Element.Events = { + mousewheel: { + base: 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll' + } +}; + +var check = function(event){ + var related = event.relatedTarget; + if (related == null) return true; + if (!related) return false; + return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related)); +}; + +if ('onmouseenter' in document.documentElement){ + Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2; + Element.MouseenterCheck = check; +} else { + Element.Events.mouseenter = { + base: 'mouseover', + condition: check + }; + + Element.Events.mouseleave = { + base: 'mouseout', + condition: check + }; +} + +/*<ltIE9>*/ +if (!window.addEventListener){ + Element.NativeEvents.propertychange = 2; + Element.Events.change = { + base: function(){ + var type = this.type; + return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change'; + }, + condition: function(event){ + return event.type != 'propertychange' || event.event.propertyName == 'checked'; + } + }; +} +/*</ltIE9>*/ + + + +})(); + + +/* +--- + +name: Element.Delegation + +description: Extends the Element native object to include the delegate method for more efficient event management. + +license: MIT-style license. + +requires: [Element.Event] + +provides: [Element.Delegation] + +... +*/ + +(function(){ + +var eventListenerSupport = !!window.addEventListener; + +Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2; + +var bubbleUp = function(self, match, fn, event, target){ + while (target && target != self){ + if (match(target, event)) return fn.call(target, event, target); + target = document.id(target.parentNode); + } +}; + +var map = { + mouseenter: { + base: 'mouseover', + condition: Element.MouseenterCheck + }, + mouseleave: { + base: 'mouseout', + condition: Element.MouseenterCheck + }, + focus: { + base: 'focus' + (eventListenerSupport ? '' : 'in'), + capture: true + }, + blur: { + base: eventListenerSupport ? 'blur' : 'focusout', + capture: true + } +}; + +/*<ltIE9>*/ +var _key = '$delegation:'; +var formObserver = function(type){ + + return { + + base: 'focusin', + + remove: function(self, uid){ + var list = self.retrieve(_key + type + 'listeners', {})[uid]; + if (list && list.forms) for (var i = list.forms.length; i--;){ + list.forms[i].removeEvent(type, list.fns[i]); + } + }, + + listen: function(self, match, fn, event, target, uid){ + var form = (target.get('tag') == 'form') ? target : event.target.getParent('form'); + if (!form) return; + + var listeners = self.retrieve(_key + type + 'listeners', {}), + listener = listeners[uid] || {forms: [], fns: []}, + forms = listener.forms, fns = listener.fns; + + if (forms.indexOf(form) != -1) return; + forms.push(form); + + var _fn = function(event){ + bubbleUp(self, match, fn, event, target); + }; + form.addEvent(type, _fn); + fns.push(_fn); + + listeners[uid] = listener; + self.store(_key + type + 'listeners', listeners); + } + }; +}; + +var inputObserver = function(type){ + return { + base: 'focusin', + listen: function(self, match, fn, event, target){ + var events = {blur: function(){ + this.removeEvents(events); + }}; + events[type] = function(event){ + bubbleUp(self, match, fn, event, target); + }; + event.target.addEvents(events); + } + }; +}; + +if (!eventListenerSupport) Object.append(map, { + submit: formObserver('submit'), + reset: formObserver('reset'), + change: inputObserver('change'), + select: inputObserver('select') +}); +/*</ltIE9>*/ + +var proto = Element.prototype, + addEvent = proto.addEvent, + removeEvent = proto.removeEvent; + +var relay = function(old, method){ + return function(type, fn, useCapture){ + if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture); + var parsed = Slick.parse(type).expressions[0][0]; + if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture); + var newType = parsed.tag; + parsed.pseudos.slice(1).each(function(pseudo){ + newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : ''); + }); + old.call(this, type, fn); + return method.call(this, newType, parsed.pseudos[0].value, fn); + }; +}; + +var delegation = { + + addEvent: function(type, match, fn){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (stored) for (var _uid in stored){ + if (stored[_uid].fn == fn && stored[_uid].match == match) return this; + } + + var _type = type, _match = match, _fn = fn, _map = map[type] || {}; + type = _map.base || _type; + + match = function(target){ + return Slick.match(target, _match); + }; + + var elementEvent = Element.Events[_type]; + if (_map.condition || elementEvent && elementEvent.condition){ + var __match = match, condition = _map.condition || elementEvent.condition; + match = function(target, event){ + return __match(target, event) && condition.call(target, event, type); + }; + } + + var self = this, uid = String.uniqueID(); + var delegator = _map.listen ? function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) _map.listen(self, match, fn, event, target, uid); + } : function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) bubbleUp(self, match, fn, event, target); + }; + + if (!stored) stored = {}; + stored[uid] = { + match: _match, + fn: _fn, + delegator: delegator + }; + storage[_type] = stored; + return addEvent.call(this, type, delegator, _map.capture); + }, + + removeEvent: function(type, match, fn, _uid){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (!stored) return this; + + if (_uid){ + var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {}; + type = _map.base || _type; + if (_map.remove) _map.remove(this, _uid); + delete stored[_uid]; + storage[_type] = stored; + return removeEvent.call(this, type, delegator, _map.capture); + } + + var __uid, s; + if (fn) for (__uid in stored){ + s = stored[__uid]; + if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid); + } else for (__uid in stored){ + s = stored[__uid]; + if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid); + } + return this; + } + +}; + +[Element, Window, Document].invoke('implement', { + addEvent: relay(addEvent, delegation.addEvent), + removeEvent: relay(removeEvent, delegation.removeEvent) +}); + +})(); + + +/* +--- + +name: Element.Dimensions + +description: Contains methods to work with size, scroll, or positioning of Elements and the window object. + +license: MIT-style license. + +credits: + - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). + - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). + +requires: [Element, Element.Style] + +provides: [Element.Dimensions] + +... +*/ + +(function(){ + +var element = document.createElement('div'), + child = document.createElement('div'); +element.style.height = '0'; +element.appendChild(child); +var brokenOffsetParent = (child.offsetParent === element); +element = child = null; + +var isOffset = function(el){ + return styleString(el, 'position') != 'static' || isBody(el); +}; + +var isOffsetStatic = function(el){ + return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName); +}; + +Element.implement({ + + scrollTo: function(x, y){ + if (isBody(this)){ + this.getWindow().scrollTo(x, y); + } else { + this.scrollLeft = x; + this.scrollTop = y; + } + return this; + }, + + getSize: function(){ + if (isBody(this)) return this.getWindow().getSize(); + return {x: this.offsetWidth, y: this.offsetHeight}; + }, + + getScrollSize: function(){ + if (isBody(this)) return this.getWindow().getScrollSize(); + return {x: this.scrollWidth, y: this.scrollHeight}; + }, + + getScroll: function(){ + if (isBody(this)) return this.getWindow().getScroll(); + return {x: this.scrollLeft, y: this.scrollTop}; + }, + + getScrolls: function(){ + var element = this.parentNode, position = {x: 0, y: 0}; + while (element && !isBody(element)){ + position.x += element.scrollLeft; + position.y += element.scrollTop; + element = element.parentNode; + } + return position; + }, + + getOffsetParent: brokenOffsetParent ? function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset; + while ((element = element.parentNode)){ + if (isOffsetCheck(element)) return element; + } + return null; + } : function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + try { + return element.offsetParent; + } catch(e) {} + return null; + }, + + getOffsets: function(){ + var hasGetBoundingClientRect = this.getBoundingClientRect; + + if (hasGetBoundingClientRect){ + var bound = this.getBoundingClientRect(), + html = document.id(this.getDocument().documentElement), + htmlScroll = html.getScroll(), + elemScrolls = this.getScrolls(), + isFixed = (styleString(this, 'position') == 'fixed'); + + return { + x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, + y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop + }; + } + + var element = this, position = {x: 0, y: 0}; + if (isBody(this)) return position; + + while (element && !isBody(element)){ + position.x += element.offsetLeft; + position.y += element.offsetTop; + + element = element.offsetParent; + } + + return position; + }, + + getPosition: function(relative){ + var offset = this.getOffsets(), + scroll = this.getScrolls(); + var position = { + x: offset.x - scroll.x, + y: offset.y - scroll.y + }; + + if (relative && (relative = document.id(relative))){ + var relativePosition = relative.getPosition(); + return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; + } + return position; + }, + + getCoordinates: function(element){ + if (isBody(this)) return this.getWindow().getCoordinates(); + var position = this.getPosition(element), + size = this.getSize(); + var obj = { + left: position.x, + top: position.y, + width: size.x, + height: size.y + }; + obj.right = obj.left + obj.width; + obj.bottom = obj.top + obj.height; + return obj; + }, + + computePosition: function(obj){ + return { + left: obj.x - styleNumber(this, 'margin-left'), + top: obj.y - styleNumber(this, 'margin-top') + }; + }, + + setPosition: function(obj){ + return this.setStyles(this.computePosition(obj)); + } + +}); + + +[Document, Window].invoke('implement', { + + getSize: function(){ + var doc = getCompatElement(this); + return {x: doc.clientWidth, y: doc.clientHeight}; + }, + + getScroll: function(){ + var win = this.getWindow(), doc = getCompatElement(this); + return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; + }, + + getScrollSize: function(){ + var doc = getCompatElement(this), + min = this.getSize(), + body = this.getDocument().body; + + return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)}; + }, + + getPosition: function(){ + return {x: 0, y: 0}; + }, + + getCoordinates: function(){ + var size = this.getSize(); + return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; + } + +}); + +// private methods + +var styleString = Element.getComputedStyle; + +function styleNumber(element, style){ + return styleString(element, style).toInt() || 0; +} + +function borderBox(element){ + return styleString(element, '-moz-box-sizing') == 'border-box'; +} + +function topBorder(element){ + return styleNumber(element, 'border-top-width'); +} + +function leftBorder(element){ + return styleNumber(element, 'border-left-width'); +} + +function isBody(element){ + return (/^(?:body|html)$/i).test(element.tagName); +} + +function getCompatElement(element){ + var doc = element.getDocument(); + return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; +} + +})(); + +//aliases +Element.alias({position: 'setPosition'}); //compatability + +[Window, Document, Element].invoke('implement', { + + getHeight: function(){ + return this.getSize().y; + }, + + getWidth: function(){ + return this.getSize().x; + }, + + getScrollTop: function(){ + return this.getScroll().y; + }, + + getScrollLeft: function(){ + return this.getScroll().x; + }, + + getScrollHeight: function(){ + return this.getScrollSize().y; + }, + + getScrollWidth: function(){ + return this.getScrollSize().x; + }, + + getTop: function(){ + return this.getPosition().y; + }, + + getLeft: function(){ + return this.getPosition().x; + } + +}); + + +/* +--- + +name: Fx + +description: Contains the basic animation logic to be extended by all other Fx Classes. + +license: MIT-style license. + +requires: [Chain, Events, Options] + +provides: Fx + +... +*/ + +(function(){ + +var Fx = this.Fx = new Class({ + + Implements: [Chain, Events, Options], + + options: { + /* + onStart: nil, + onCancel: nil, + onComplete: nil, + */ + fps: 60, + unit: false, + duration: 500, + frames: null, + frameSkip: true, + link: 'ignore' + }, + + initialize: function(options){ + this.subject = this.subject || this; + this.setOptions(options); + }, + + getTransition: function(){ + return function(p){ + return -(Math.cos(Math.PI * p) - 1) / 2; + }; + }, + + step: function(now){ + if (this.options.frameSkip){ + var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval; + this.time = now; + this.frame += frames; + } else { + this.frame++; + } + + if (this.frame < this.frames){ + var delta = this.transition(this.frame / this.frames); + this.set(this.compute(this.from, this.to, delta)); + } else { + this.frame = this.frames; + this.set(this.compute(this.from, this.to, 1)); + this.stop(); + } + }, + + set: function(now){ + return now; + }, + + compute: function(from, to, delta){ + return Fx.compute(from, to, delta); + }, + + check: function(){ + if (!this.isRunning()) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + start: function(from, to){ + if (!this.check(from, to)) return this; + this.from = from; + this.to = to; + this.frame = (this.options.frameSkip) ? 0 : -1; + this.time = null; + this.transition = this.getTransition(); + var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration; + this.duration = Fx.Durations[duration] || duration.toInt(); + this.frameInterval = 1000 / fps; + this.frames = frames || Math.round(this.duration / this.frameInterval); + this.fireEvent('start', this.subject); + pushInstance.call(this, fps); + return this; + }, + + stop: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + if (this.frames == this.frame){ + this.fireEvent('complete', this.subject); + if (!this.callChain()) this.fireEvent('chainComplete', this.subject); + } else { + this.fireEvent('stop', this.subject); + } + } + return this; + }, + + cancel: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + this.frame = this.frames; + this.fireEvent('cancel', this.subject).clearChain(); + } + return this; + }, + + pause: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + } + return this; + }, + + resume: function(){ + if (this.isPaused()) pushInstance.call(this, this.options.fps); + return this; + }, + + isRunning: function(){ + var list = instances[this.options.fps]; + return list && list.contains(this); + }, + + isPaused: function(){ + return (this.frame < this.frames) && !this.isRunning(); + } + +}); + +Fx.compute = function(from, to, delta){ + return (to - from) * delta + from; +}; + +Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; + +// global timers + +var instances = {}, timers = {}; + +var loop = function(){ + var now = Date.now(); + for (var i = this.length; i--;){ + var instance = this[i]; + if (instance) instance.step(now); + } +}; + +var pushInstance = function(fps){ + var list = instances[fps] || (instances[fps] = []); + list.push(this); + if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list); +}; + +var pullInstance = function(fps){ + var list = instances[fps]; + if (list){ + list.erase(this); + if (!list.length && timers[fps]){ + delete instances[fps]; + timers[fps] = clearInterval(timers[fps]); + } + } +}; + +})(); + + +/* +--- + +name: Fx.CSS + +description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. + +license: MIT-style license. + +requires: [Fx, Element.Style] + +provides: Fx.CSS + +... +*/ + +Fx.CSS = new Class({ + + Extends: Fx, + + //prepares the base from/to object + + prepare: function(element, property, values){ + values = Array.from(values); + var from = values[0], to = values[1]; + if (to == null){ + to = from; + from = element.getStyle(property); + var unit = this.options.unit; + // adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299 + if (unit && from && typeof from == 'string' && from.slice(-unit.length) != unit && parseFloat(from) != 0){ + element.setStyle(property, to + unit); + var value = element.getComputedStyle(property); + // IE and Opera support pixelLeft or pixelWidth + if (!(/px$/.test(value))){ + value = element.style[('pixel-' + property).camelCase()]; + if (value == null){ + // adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + var left = element.style.left; + element.style.left = to + unit; + value = element.style.pixelLeft; + element.style.left = left; + } + } + from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0); + element.setStyle(property, from + unit); + } + } + return {from: this.parse(from), to: this.parse(to)}; + }, + + //parses a value into an array + + parse: function(value){ + value = Function.from(value)(); + value = (typeof value == 'string') ? value.split(' ') : Array.from(value); + return value.map(function(val){ + val = String(val); + var found = false; + Object.each(Fx.CSS.Parsers, function(parser, key){ + if (found) return; + var parsed = parser.parse(val); + if (parsed || parsed === 0) found = {value: parsed, parser: parser}; + }); + found = found || {value: val, parser: Fx.CSS.Parsers.String}; + return found; + }); + }, + + //computes by a from and to prepared objects, using their parsers. + + compute: function(from, to, delta){ + var computed = []; + (Math.min(from.length, to.length)).times(function(i){ + computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); + }); + computed.$family = Function.from('fx:css:value'); + return computed; + }, + + //serves the value as settable + + serve: function(value, unit){ + if (typeOf(value) != 'fx:css:value') value = this.parse(value); + var returned = []; + value.each(function(bit){ + returned = returned.concat(bit.parser.serve(bit.value, unit)); + }); + return returned; + }, + + //renders the change to an element + + render: function(element, property, value, unit){ + element.setStyle(property, this.serve(value, unit)); + }, + + //searches inside the page css to find the values for a selector + + search: function(selector){ + if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; + var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); + + var searchStyles = function(rules){ + Array.each(rules, function(rule, i){ + if (rule.media){ + searchStyles(rule.rules || rule.cssRules); + return; + } + if (!rule.style) return; + var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ + return m.toLowerCase(); + }) : null; + if (!selectorText || !selectorTest.test(selectorText)) return; + Object.each(Element.Styles, function(value, style){ + if (!rule.style[style] || Element.ShortStyles[style]) return; + value = String(rule.style[style]); + to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; + }); + }); + }; + + Array.each(document.styleSheets, function(sheet, j){ + var href = sheet.href; + if (href && href.indexOf('://') > -1 && href.indexOf(document.domain) == -1) return; + var rules = sheet.rules || sheet.cssRules; + searchStyles(rules); + }); + return Fx.CSS.Cache[selector] = to; + } + +}); + +Fx.CSS.Cache = {}; + +Fx.CSS.Parsers = { + + Color: { + parse: function(value){ + if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); + return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; + }, + compute: function(from, to, delta){ + return from.map(function(value, i){ + return Math.round(Fx.compute(from[i], to[i], delta)); + }); + }, + serve: function(value){ + return value.map(Number); + } + }, + + Number: { + parse: parseFloat, + compute: Fx.compute, + serve: function(value, unit){ + return (unit) ? value + unit : value; + } + }, + + String: { + parse: Function.from(false), + compute: function(zero, one){ + return one; + }, + serve: function(zero){ + return zero; + } + } + +}; + + + + +/* +--- + +name: Fx.Tween + +description: Formerly Fx.Style, effect to transition any CSS property for an element. + +license: MIT-style license. + +requires: Fx.CSS + +provides: [Fx.Tween, Element.fade, Element.highlight] + +... +*/ + +Fx.Tween = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(property, now){ + if (arguments.length == 1){ + now = property; + property = this.property || this.options.property; + } + this.render(this.element, property, now, this.options.unit); + return this; + }, + + start: function(property, from, to){ + if (!this.check(property, from, to)) return this; + var args = Array.flatten(arguments); + this.property = this.options.property || args.shift(); + var parsed = this.prepare(this.element, this.property, args); + return this.parent(parsed.from, parsed.to); + } + +}); + +Element.Properties.tween = { + + set: function(options){ + this.get('tween').cancel().setOptions(options); + return this; + }, + + get: function(){ + var tween = this.retrieve('tween'); + if (!tween){ + tween = new Fx.Tween(this, {link: 'cancel'}); + this.store('tween', tween); + } + return tween; + } + +}; + +Element.implement({ + + tween: function(property, from, to){ + this.get('tween').start(property, from, to); + return this; + }, + + fade: function(how){ + var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle; + if (args[1] == null) args[1] = 'toggle'; + switch (args[1]){ + case 'in': method = 'start'; args[1] = 1; break; + case 'out': method = 'start'; args[1] = 0; break; + case 'show': method = 'set'; args[1] = 1; break; + case 'hide': method = 'set'; args[1] = 0; break; + case 'toggle': + var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1); + method = 'start'; + args[1] = flag ? 0 : 1; + this.store('fade:flag', !flag); + toggle = true; + break; + default: method = 'start'; + } + if (!toggle) this.eliminate('fade:flag'); + fade[method].apply(fade, args); + var to = args[args.length - 1]; + if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible'); + else fade.chain(function(){ + this.element.setStyle('visibility', 'hidden'); + this.callChain(); + }); + return this; + }, + + highlight: function(start, end){ + if (!end){ + end = this.retrieve('highlight:original', this.getStyle('background-color')); + end = (end == 'transparent') ? '#fff' : end; + } + var tween = this.get('tween'); + tween.start('background-color', start || '#ffff88', end).chain(function(){ + this.setStyle('background-color', this.retrieve('highlight:original')); + tween.callChain(); + }.bind(this)); + return this; + } + +}); + + +/* +--- + +name: Fx.Morph + +description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. + +license: MIT-style license. + +requires: Fx.CSS + +provides: Fx.Morph + +... +*/ + +Fx.Morph = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(now){ + if (typeof now == 'string') now = this.search(now); + for (var p in now) this.render(this.element, p, now[p], this.options.unit); + return this; + }, + + compute: function(from, to, delta){ + var now = {}; + for (var p in from) now[p] = this.parent(from[p], to[p], delta); + return now; + }, + + start: function(properties){ + if (!this.check(properties)) return this; + if (typeof properties == 'string') properties = this.search(properties); + var from = {}, to = {}; + for (var p in properties){ + var parsed = this.prepare(this.element, p, properties[p]); + from[p] = parsed.from; + to[p] = parsed.to; + } + return this.parent(from, to); + } + +}); + +Element.Properties.morph = { + + set: function(options){ + this.get('morph').cancel().setOptions(options); + return this; + }, + + get: function(){ + var morph = this.retrieve('morph'); + if (!morph){ + morph = new Fx.Morph(this, {link: 'cancel'}); + this.store('morph', morph); + } + return morph; + } + +}; + +Element.implement({ + + morph: function(props){ + this.get('morph').start(props); + return this; + } + +}); + + +/* +--- + +name: Fx.Transitions + +description: Contains a set of advanced transitions to be used with any of the Fx Classes. + +license: MIT-style license. + +credits: + - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. + +requires: Fx + +provides: Fx.Transitions + +... +*/ + +Fx.implement({ + + getTransition: function(){ + var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; + if (typeof trans == 'string'){ + var data = trans.split(':'); + trans = Fx.Transitions; + trans = trans[data[0]] || trans[data[0].capitalize()]; + if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; + } + return trans; + } + +}); + +Fx.Transition = function(transition, params){ + params = Array.from(params); + var easeIn = function(pos){ + return transition(pos, params); + }; + return Object.append(easeIn, { + easeIn: easeIn, + easeOut: function(pos){ + return 1 - transition(1 - pos, params); + }, + easeInOut: function(pos){ + return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2; + } + }); +}; + +Fx.Transitions = { + + linear: function(zero){ + return zero; + } + +}; + + + +Fx.Transitions.extend = function(transitions){ + for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); +}; + +Fx.Transitions.extend({ + + Pow: function(p, x){ + return Math.pow(p, x && x[0] || 6); + }, + + Expo: function(p){ + return Math.pow(2, 8 * (p - 1)); + }, + + Circ: function(p){ + return 1 - Math.sin(Math.acos(p)); + }, + + Sine: function(p){ + return 1 - Math.cos(p * Math.PI / 2); + }, + + Back: function(p, x){ + x = x && x[0] || 1.618; + return Math.pow(p, 2) * ((x + 1) * p - x); + }, + + Bounce: function(p){ + var value; + for (var a = 0, b = 1; 1; a += b, b /= 2){ + if (p >= (7 - 4 * a) / 11){ + value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); + break; + } + } + return value; + }, + + Elastic: function(p, x){ + return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3); + } + +}); + +['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ + Fx.Transitions[transition] = new Fx.Transition(function(p){ + return Math.pow(p, i + 2); + }); +}); + + +/* +--- + +name: Request + +description: Powerful all purpose Request Class. Uses XMLHTTPRequest. + +license: MIT-style license. + +requires: [Object, Element, Chain, Events, Options, Browser] + +provides: Request + +... +*/ + +(function(){ + +var empty = function(){}, + progressSupport = ('onprogress' in new Browser.Request); + +var Request = this.Request = new Class({ + + Implements: [Chain, Events, Options], + + options: {/* + onRequest: function(){}, + onLoadstart: function(event, xhr){}, + onProgress: function(event, xhr){}, + onComplete: function(){}, + onCancel: function(){}, + onSuccess: function(responseText, responseXML){}, + onFailure: function(xhr){}, + onException: function(headerName, value){}, + onTimeout: function(){}, + user: '', + password: '',*/ + url: '', + data: '', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }, + async: true, + format: false, + method: 'post', + link: 'ignore', + isSuccess: null, + emulation: true, + urlEncoded: true, + encoding: 'utf-8', + evalScripts: false, + evalResponse: false, + timeout: 0, + noCache: false + }, + + initialize: function(options){ + this.xhr = new Browser.Request(); + this.setOptions(options); + this.headers = this.options.headers; + }, + + onStateChange: function(){ + var xhr = this.xhr; + if (xhr.readyState != 4 || !this.running) return; + this.running = false; + this.status = 0; + Function.attempt(function(){ + var status = xhr.status; + this.status = (status == 1223) ? 204 : status; + }.bind(this)); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + clearTimeout(this.timer); + + this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; + if (this.options.isSuccess.call(this, this.status)) + this.success(this.response.text, this.response.xml); + else + this.failure(); + }, + + isSuccess: function(){ + var status = this.status; + return (status >= 200 && status < 300); + }, + + isRunning: function(){ + return !!this.running; + }, + + processScripts: function(text){ + if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text); + return text.stripScripts(this.options.evalScripts); + }, + + success: function(text, xml){ + this.onSuccess(this.processScripts(text), xml); + }, + + onSuccess: function(){ + this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); + }, + + failure: function(){ + this.onFailure(); + }, + + onFailure: function(){ + this.fireEvent('complete').fireEvent('failure', this.xhr); + }, + + loadstart: function(event){ + this.fireEvent('loadstart', [event, this.xhr]); + }, + + progress: function(event){ + this.fireEvent('progress', [event, this.xhr]); + }, + + timeout: function(){ + this.fireEvent('timeout', this.xhr); + }, + + setHeader: function(name, value){ + this.headers[name] = value; + return this; + }, + + getHeader: function(name){ + return Function.attempt(function(){ + return this.xhr.getResponseHeader(name); + }.bind(this)); + }, + + check: function(){ + if (!this.running) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + send: function(options){ + if (!this.check(options)) return this; + + this.options.isSuccess = this.options.isSuccess || this.isSuccess; + this.running = true; + + var type = typeOf(options); + if (type == 'string' || type == 'element') options = {data: options}; + + var old = this.options; + options = Object.append({data: old.data, url: old.url, method: old.method}, options); + var data = options.data, url = String(options.url), method = options.method.toLowerCase(); + + switch (typeOf(data)){ + case 'element': data = document.id(data).toQueryString(); break; + case 'object': case 'hash': data = Object.toQueryString(data); + } + + if (this.options.format){ + var format = 'format=' + this.options.format; + data = (data) ? format + '&' + data : format; + } + + if (this.options.emulation && !['get', 'post'].contains(method)){ + var _method = '_method=' + method; + data = (data) ? _method + '&' + data : _method; + method = 'post'; + } + + if (this.options.urlEncoded && ['post', 'put'].contains(method)){ + var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; + this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; + } + + if (!url) url = document.location.pathname; + + var trimPosition = url.lastIndexOf('/'); + if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); + + if (this.options.noCache) + url += (url.indexOf('?') > -1 ? '&' : '?') + String.uniqueID(); + + if (data && (method == 'get' || method == 'delete')){ + url += (url.indexOf('?') > -1 ? '&' : '?') + data; + data = null; + } + + var xhr = this.xhr; + if (progressSupport){ + xhr.onloadstart = this.loadstart.bind(this); + xhr.onprogress = this.progress.bind(this); + } + + xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); + if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; + + xhr.onreadystatechange = this.onStateChange.bind(this); + + Object.each(this.headers, function(value, key){ + try { + xhr.setRequestHeader(key, value); + } catch (e){ + this.fireEvent('exception', [key, value]); + } + }, this); + + this.fireEvent('request'); + xhr.send(data); + if (!this.options.async) this.onStateChange(); + else if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this); + return this; + }, + + cancel: function(){ + if (!this.running) return this; + this.running = false; + var xhr = this.xhr; + xhr.abort(); + clearTimeout(this.timer); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + this.xhr = new Browser.Request(); + this.fireEvent('cancel'); + return this; + } + +}); + +var methods = {}; +['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ + methods[method] = function(data){ + var object = { + method: method + }; + if (data != null) object.data = data; + return this.send(object); + }; +}); + +Request.implement(methods); + +Element.Properties.send = { + + set: function(options){ + var send = this.get('send').cancel(); + send.setOptions(options); + return this; + }, + + get: function(){ + var send = this.retrieve('send'); + if (!send){ + send = new Request({ + data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') + }); + this.store('send', send); + } + return send; + } + +}; + +Element.implement({ + + send: function(url){ + var sender = this.get('send'); + sender.send({data: this, url: url || sender.options.url}); + return this; + } + +}); + +})(); + + +/* +--- + +name: Request.HTML + +description: Extends the basic Request Class with additional methods for interacting with HTML responses. + +license: MIT-style license. + +requires: [Element, Request] + +provides: Request.HTML + +... +*/ + +Request.HTML = new Class({ + + Extends: Request, + + options: { + update: false, + append: false, + evalScripts: true, + filter: false, + headers: { + Accept: 'text/html, application/xml, text/xml, */*' + } + }, + + success: function(text){ + var options = this.options, response = this.response; + + response.html = text.stripScripts(function(script){ + response.javascript = script; + }); + + var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); + if (match) response.html = match[1]; + var temp = new Element('div').set('html', response.html); + + response.tree = temp.childNodes; + response.elements = temp.getElements(options.filter || '*'); + + if (options.filter) response.tree = response.elements; + if (options.update){ + var update = document.id(options.update).empty(); + if (options.filter) update.adopt(response.elements); + else update.set('html', response.html); + } else if (options.append){ + var append = document.id(options.append); + if (options.filter) response.elements.reverse().inject(append); + else append.adopt(temp.getChildren()); + } + if (options.evalScripts) Browser.exec(response.javascript); + + this.onSuccess(response.tree, response.elements, response.html, response.javascript); + } + +}); + +Element.Properties.load = { + + set: function(options){ + var load = this.get('load').cancel(); + load.setOptions(options); + return this; + }, + + get: function(){ + var load = this.retrieve('load'); + if (!load){ + load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'}); + this.store('load', load); + } + return load; + } + +}; + +Element.implement({ + + load: function(){ + this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString})); + return this; + } + +}); + + +/* +--- + +name: JSON + +description: JSON encoder and decoder. + +license: MIT-style license. + +SeeAlso: <http://www.json.org/> + +requires: [Array, String, Number, Function] + +provides: JSON + +... +*/ + +if (typeof JSON == 'undefined') this.JSON = {}; + + + +(function(){ + +var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; + +var escape = function(chr){ + return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); +}; + +JSON.validate = function(string){ + string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''); + + return (/^[\],:{}\s]*$/).test(string); +}; + +JSON.encode = JSON.stringify ? function(obj){ + return JSON.stringify(obj); +} : function(obj){ + if (obj && obj.toJSON) obj = obj.toJSON(); + + switch (typeOf(obj)){ + case 'string': + return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; + case 'array': + return '[' + obj.map(JSON.encode).clean() + ']'; + case 'object': case 'hash': + var string = []; + Object.each(obj, function(value, key){ + var json = JSON.encode(value); + if (json) string.push(JSON.encode(key) + ':' + json); + }); + return '{' + string + '}'; + case 'number': case 'boolean': return '' + obj; + case 'null': return 'null'; + } + + return null; +}; + +JSON.secure = true; + + +JSON.decode = function(string, secure){ + if (!string || typeOf(string) != 'string') return null; + + if (secure == null) secure = JSON.secure; + if (secure){ + if (JSON.parse) return JSON.parse(string); + if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); + } + + return eval('(' + string + ')'); +}; + +})(); + + +/* +--- + +name: Request.JSON + +description: Extends the basic Request Class with additional methods for sending and receiving JSON data. + +license: MIT-style license. + +requires: [Request, JSON] + +provides: Request.JSON + +... +*/ + +Request.JSON = new Class({ + + Extends: Request, + + options: { + /*onError: function(text, error){},*/ + secure: true + }, + + initialize: function(options){ + this.parent(options); + Object.append(this.headers, { + 'Accept': 'application/json', + 'X-Request': 'JSON' + }); + }, + + success: function(text){ + var json; + try { + json = this.response.json = JSON.decode(text, this.options.secure); + } catch (error){ + this.fireEvent('error', [text, error]); + return; + } + if (json == null) this.onFailure(); + else this.onSuccess(json, text); + } + +}); + + +/* +--- + +name: Cookie + +description: Class for creating, reading, and deleting browser Cookies. + +license: MIT-style license. + +credits: + - Based on the functions by Peter-Paul Koch (http://quirksmode.org). + +requires: [Options, Browser] + +provides: Cookie + +... +*/ + +var Cookie = new Class({ + + Implements: Options, + + options: { + path: '/', + domain: false, + duration: false, + secure: false, + document: document, + encode: true + }, + + initialize: function(key, options){ + this.key = key; + this.setOptions(options); + }, + + write: function(value){ + if (this.options.encode) value = encodeURIComponent(value); + if (this.options.domain) value += '; domain=' + this.options.domain; + if (this.options.path) value += '; path=' + this.options.path; + if (this.options.duration){ + var date = new Date(); + date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); + value += '; expires=' + date.toGMTString(); + } + if (this.options.secure) value += '; secure'; + this.options.document.cookie = this.key + '=' + value; + return this; + }, + + read: function(){ + var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); + return (value) ? decodeURIComponent(value[1]) : null; + }, + + dispose: function(){ + new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write(''); + return this; + } + +}); + +Cookie.write = function(key, value, options){ + return new Cookie(key, options).write(value); +}; + +Cookie.read = function(key){ + return new Cookie(key).read(); +}; + +Cookie.dispose = function(key, options){ + return new Cookie(key, options).dispose(); +}; + + +/* +--- + +name: DOMReady + +description: Contains the custom event domready. + +license: MIT-style license. + +requires: [Browser, Element, Element.Event] + +provides: [DOMReady, DomReady] + +... +*/ + +(function(window, document){ + +var ready, + loaded, + checks = [], + shouldPoll, + timer, + testElement = document.createElement('div'); + +var domready = function(){ + clearTimeout(timer); + if (ready) return; + Browser.loaded = ready = true; + document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); + + document.fireEvent('domready'); + window.fireEvent('domready'); +}; + +var check = function(){ + for (var i = checks.length; i--;) if (checks[i]()){ + domready(); + return true; + } + return false; +}; + +var poll = function(){ + clearTimeout(timer); + if (!check()) timer = setTimeout(poll, 10); +}; + +document.addListener('DOMContentLoaded', domready); + +/*<ltIE8>*/ +// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/ +// testElement.doScroll() throws when the DOM is not ready, only in the top window +var doScrollWorks = function(){ + try { + testElement.doScroll(); + return true; + } catch (e){} + return false; +}; +// If doScroll works already, it can't be used to determine domready +// e.g. in an iframe +if (testElement.doScroll && !doScrollWorks()){ + checks.push(doScrollWorks); + shouldPoll = true; +} +/*</ltIE8>*/ + +if (document.readyState) checks.push(function(){ + var state = document.readyState; + return (state == 'loaded' || state == 'complete'); +}); + +if ('onreadystatechange' in document) document.addListener('readystatechange', check); +else shouldPoll = true; + +if (shouldPoll) poll(); + +Element.Events.domready = { + onAdd: function(fn){ + if (ready) fn.call(this); + } +}; + +// Make sure that domready fires before load +Element.Events.load = { + base: 'load', + onAdd: function(fn){ + if (loaded && this == window) fn.call(this); + }, + condition: function(){ + if (this == window){ + domready(); + delete Element.Events.load; + } + return true; + } +}; + +// This is based on the custom load event +window.addEvent('load', function(){ + loaded = true; +}); + +})(window, document); + diff --git a/module/web/media/js/mootools-core-1.4.1.js b/module/webui/themes/dark/js/static/mootools-core.min.js index 835b4bbe2..354f94196 100644 --- a/module/web/media/js/mootools-core-1.4.1.js +++ b/module/webui/themes/dark/js/static/mootools-core.min.js @@ -3,10 +3,10 @@ MooTools: the javascript framework web build: - - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0 + - http://mootools.net/core/8423c12ffd6a6bfcde9ea22554aec795 packager build: - - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady copyrights: - [MooTools](http://mootools.net) @@ -15,24 +15,26 @@ licenses: - [MIT License](http://mootools.net/license.txt) ... */ -(function(){this.MooTools={version:"1.4.1",build:"d1fb25710e3c5482a219ab9dc675a4e0ad2176b6"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family){return i.$family(); -}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if(i.callee){return"arguments"; + +(function(){this.MooTools={version:"1.5.0",build:"0f7b690afee9349b15909f33016a25d2e4d9f4e3"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family!=null){return i.$family(); +}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if("callee" in i){return"arguments"; }if("item" in i){return"collection";}}}return typeof i;};var j=this.instanceOf=function(t,i){if(t==null){return false;}var s=t.$constructor||t.constructor; -while(s){if(s===i){return true;}s=s.parent;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null;}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"]; -}f.prototype.overloadSetter=function(s){var i=this;return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]); -}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]);}}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this; -return function(u){var v,t;if(s||typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments;}}if(v){t={};for(var w=0;w<v.length;w++){t[v[w]]=i.call(this,v[w]); -}}else{t=i.call(this,u);}return t;};};f.prototype.extend=function(i,s){this[i]=s;}.overloadSetter();f.prototype.implement=function(i,s){this.prototype[i]=s; -}.overloadSetter();var n=Array.prototype.slice;f.from=function(i){return(o(i)=="function")?i:function(){return i;};};Array.from=function(i){if(i==null){return[]; -}return(a.isEnumerable(i)&&typeof i!="string")?(o(i)=="array")?i:n.call(i):[i];};Number.from=function(s){var i=parseFloat(s);return isFinite(i)?i:null; -};String.from=function(i){return i+"";};f.implement({hide:function(){this.$hidden=true;return this;},protect:function(){this.$protected=true;return this; -}});var a=this.Type=function(u,t){if(u){var s=u.toLowerCase();var i=function(v){return(o(v)==s);};a["is"+u]=i;if(t!=null){t.prototype.$family=(function(){return s; +while(s){if(s===i){return true;}s=s.parent;}if(!t.hasOwnProperty){return false;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null; +}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];}f.prototype.overloadSetter=function(s){var i=this; +return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]);}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]); +}}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this;return function(u){var v,t;if(typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments; +}else{if(s){v=[u];}}}if(v){t={};for(var w=0;w<v.length;w++){t[v[w]]=i.call(this,v[w]);}}else{t=i.call(this,u);}return t;};};f.prototype.extend=function(i,s){this[i]=s; +}.overloadSetter();f.prototype.implement=function(i,s){this.prototype[i]=s;}.overloadSetter();var n=Array.prototype.slice;f.from=function(i){return(o(i)=="function")?i:function(){return i; +};};Array.from=function(i){if(i==null){return[];}return(a.isEnumerable(i)&&typeof i!="string")?(o(i)=="array")?i:n.call(i):[i];};Number.from=function(s){var i=parseFloat(s); +return isFinite(i)?i:null;};String.from=function(i){return i+"";};f.implement({hide:function(){this.$hidden=true;return this;},protect:function(){this.$protected=true; +return this;}});var a=this.Type=function(u,t){if(u){var s=u.toLowerCase();var i=function(v){return(o(v)==s);};a["is"+u]=i;if(t!=null){t.prototype.$family=(function(){return s; }).hide();}}if(t==null){return null;}t.extend(this);t.$constructor=a;t.prototype.$constructor=t;return t;};var e=Object.prototype.toString;a.isEnumerable=function(i){return(i!=null&&typeof i.length=="number"&&e.call(i)!="[object Function]"); };var q={};var r=function(i){var s=o(i.prototype);return q[s]||(q[s]=[]);};var b=function(t,x){if(x&&x.$hidden){return;}var s=r(this);for(var u=0;u<s.length; u++){var w=s[u];if(o(w)=="type"){b.call(w,t,x);}else{w.call(this,t,x);}}var v=this.prototype[t];if(v==null||!v.$protected){this.prototype[t]=x;}if(this[t]==null&&o(x)=="function"){m.call(this,t,function(i){return x.apply(i,n.call(arguments,1)); });}};var m=function(i,t){if(t&&t.$hidden){return;}var s=this[i];if(s==null||!s.$protected){this[i]=t;}};a.implement({implement:b.overloadSetter(),extend:m.overloadSetter(),alias:function(i,s){b.call(this,i,this.prototype[s]); -}.overloadSetter(),mirror:function(i){r(this).push(i);return this;}});new a("Type",a);var d=function(s,w,u){var t=(w!=Object),A=w.prototype;if(t){w=new a(s,w); -}for(var x=0,v=u.length;x<v;x++){var B=u[x],z=w[B],y=A[B];if(z){z.protect();}if(t&&y){delete A[B];A[B]=y.protect();}}if(t){w.implement(A);}return d;};d("String",String,["charAt","charCodeAt","concat","indexOf","lastIndexOf","match","quote","replace","search","slice","split","substr","substring","trim","toLowerCase","toUpperCase"])("Array",Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"])("Number",Number,["toExponential","toFixed","toLocaleString","toPrecision"])("Function",f,["apply","call","bind"])("RegExp",RegExp,["exec","test"])("Object",Object,["create","defineProperty","defineProperties","keys","getPrototypeOf","getOwnPropertyDescriptor","getOwnPropertyNames","preventExtensions","isExtensible","seal","isSealed","freeze","isFrozen"])("Date",Date,["now"]); +}.overloadSetter(),mirror:function(i){r(this).push(i);return this;}});new a("Type",a);var d=function(s,x,v){var u=(x!=Object),B=x.prototype;if(u){x=new a(s,x); +}for(var y=0,w=v.length;y<w;y++){var C=v[y],A=x[C],z=B[C];if(A){A.protect();}if(u&&z){x.implement(C,z.protect());}}if(u){var t=B.propertyIsEnumerable(v[0]); +x.forEachMethod=function(G){if(!t){for(var F=0,D=v.length;F<D;F++){G.call(B,B[v[F]],v[F]);}}for(var E in B){G.call(B,B[E],E);}};}return d;};d("String",String,["charAt","charCodeAt","concat","contains","indexOf","lastIndexOf","match","quote","replace","search","slice","split","substr","substring","trim","toLowerCase","toUpperCase"])("Array",Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"])("Number",Number,["toExponential","toFixed","toLocaleString","toPrecision"])("Function",f,["apply","call","bind"])("RegExp",RegExp,["exec","test"])("Object",Object,["create","defineProperty","defineProperties","keys","getPrototypeOf","getOwnPropertyDescriptor","getOwnPropertyNames","preventExtensions","isExtensible","seal","isSealed","freeze","isFrozen"])("Date",Date,["now"]); Object.extend=m.overloadSetter();Date.extend("now",function(){return +(new Date);});new a("Boolean",Boolean);Number.prototype.$family=function(){return isFinite(this)?"number":"null"; }.hide();Number.extend("random",function(s,i){return Math.floor(Math.random()*(i-s+1)+s);});var g=Object.prototype.hasOwnProperty;Object.extend("forEach",function(i,t,u){for(var s in i){if(g.call(i,s)){t.call(u,i[s],s,i); }}});Object.each=Object.forEach;Array.implement({forEach:function(u,v){for(var t=0,s=this.length;t<s;t++){if(t in this){u.call(v,this[t],t,this);}}},each:function(i,s){Array.forEach(this,i,s); @@ -42,21 +44,21 @@ while(s--){t[s]=l(this[s]);}return t;});var h=function(s,i,t){switch(o(t)){case" y<s;y++){var w=arguments[y];for(var x in w){h(z,x,w[x]);}}return z;},clone:function(i){var t={};for(var s in i){t[s]=l(i[s]);}return t;},append:function(w){for(var v=1,t=arguments.length; v<t;v++){var s=arguments[v]||{};for(var u in s){w[u]=s[u];}}return w;}});["Object","WhiteSpace","TextNode","Collection","Arguments"].each(function(i){new a(i); });var c=Date.now();String.extend("uniqueID",function(){return(c++).toString(36);});})();Array.implement({every:function(c,d){for(var b=0,a=this.length>>>0; -b<a;b++){if((b in this)&&!c.call(d,this[b],b,this)){return false;}}return true;},filter:function(d,e){var c=[];for(var b=0,a=this.length>>>0;b<a;b++){if((b in this)&&d.call(e,this[b],b,this)){c.push(this[b]); -}}return c;},indexOf:function(c,d){var b=this.length>>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a<b;a++){if(this[a]===c){return a;}}return -1;},map:function(c,e){var d=this.length>>>0,b=Array(d); -for(var a=0;a<d;a++){if(a in this){b[a]=c.call(e,this[a],a,this);}}return b;},some:function(c,d){for(var b=0,a=this.length>>>0;b<a;b++){if((b in this)&&c.call(d,this[b],b,this)){return true; -}}return false;},clean:function(){return this.filter(function(a){return a!=null;});},invoke:function(a){var b=Array.slice(arguments,1);return this.map(function(c){return c[a].apply(c,b); -});},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a];}return d;},link:function(c){var a={};for(var e=0,b=this.length; -e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1;},append:function(a){this.push.apply(this,a); -return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[Number.random(0,this.length-1)]:null; +b<a;b++){if((b in this)&&!c.call(d,this[b],b,this)){return false;}}return true;},filter:function(d,f){var c=[];for(var e,b=0,a=this.length>>>0;b<a;b++){if(b in this){e=this[b]; +if(d.call(f,e,b,this)){c.push(e);}}}return c;},indexOf:function(c,d){var b=this.length>>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a<b;a++){if(this[a]===c){return a; +}}return -1;},map:function(c,e){var d=this.length>>>0,b=Array(d);for(var a=0;a<d;a++){if(a in this){b[a]=c.call(e,this[a],a,this);}}return b;},some:function(c,d){for(var b=0,a=this.length>>>0; +b<a;b++){if((b in this)&&c.call(d,this[b],b,this)){return true;}}return false;},clean:function(){return this.filter(function(a){return a!=null;});},invoke:function(a){var b=Array.slice(arguments,1); +return this.map(function(c){return c[a].apply(c,b);});},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a]; +}return d;},link:function(c){var a={};for(var e=0,b=this.length;e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1; +},append:function(a){this.push.apply(this,a);return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[Number.random(0,this.length-1)]:null; },include:function(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this; },erase:function(b){for(var a=this.length;a--;){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[]; for(var b=0,a=this.length;b<a;b++){var c=typeOf(this[b]);if(c=="null"){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments"||instanceOf(this[b],Array))?Array.flatten(this[b]):this[b]); }return d;},pick:function(){for(var b=0,a=this.length;b<a;b++){if(this[b]!=null){return this[b];}}return null;},hexToRgb:function(b){if(this.length!=3){return null; -}var a=this.map(function(c){if(c.length==1){c+=c;}return c.toInt(16);});return(b)?a:"rgb("+a+")";},rgbToHex:function(d){if(this.length<3){return null;}if(this.length==4&&this[3]==0&&!d){return"transparent"; -}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join("");}});String.implement({test:function(a,b){return((typeOf(a)=="regexp")?a:new RegExp(""+a,b)).test(this); -},contains:function(a,b){return(b)?(b+this+b).indexOf(b+a+b)>-1:String(this).indexOf(a)>-1;},trim:function(){return String(this).replace(/^\s+|\s+$/g,""); -},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase(); +}var a=this.map(function(c){if(c.length==1){c+=c;}return parseInt(c,16);});return(b)?a:"rgb("+a+")";},rgbToHex:function(d){if(this.length<3){return null; +}if(this.length==4&&this[3]==0&&!d){return"transparent";}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join(""); +}});String.implement({contains:function(b,a){return(a?String(this).slice(a):String(this)).indexOf(b)>-1;},test:function(a,b){return((typeOf(a)=="regexp")?a:new RegExp(""+a,b)).test(this); +},trim:function(){return String(this).replace(/^\s+|\s+$/g,"");},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase(); });},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase(); });},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this); },hexToRgb:function(b){var a=String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g); @@ -76,25 +78,25 @@ for(var e=0,b=g.length;e<b;e++){var c=g[e];if(c in d){f[c]=d[c];}}return f;},map }}return d;},values:function(c){var b=[];for(var d in c){if(a.call(c,d)){b.push(c[d]);}}return b;},getLength:function(b){return Object.keys(b).length;},keyOf:function(b,d){for(var c in b){if(a.call(b,c)&&b[c]===d){return c; }}return null;},contains:function(b,c){return Object.keyOf(b,c)!=null;},toQueryString:function(b,c){var d=[];Object.each(b,function(h,g){if(c){g=c+"["+g+"]"; }var f;switch(typeOf(h)){case"object":f=Object.toQueryString(h,g);break;case"array":var e={};h.each(function(k,j){e[j]=k;});f=Object.toQueryString(e,g); -break;default:f=g+"="+encodeURIComponent(h);}if(h!=null){d.push(f);}});return d.join("&");}});})();(function(){var k=this.document;var i=k.window=this; -var b=1;this.$uid=(i.ActiveXObject)?function(e){return(e.uid||(e.uid=[b++]))[0];}:function(e){return e.uid||(e.uid=b++);};$uid(i);$uid(k);var a=navigator.userAgent.toLowerCase(),c=navigator.platform.toLowerCase(),j=a.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,"unknown",0],f=j[1]=="ie"&&k.documentMode; -var o=this.Browser={extend:Function.prototype.extend,name:(j[1]=="version")?j[3]:j[1],version:f||parseFloat((j[1]=="opera"&&j[4])?j[4]:j[2]),Platform:{name:a.match(/ip(?:ad|od|hone)/)?"ios":(a.match(/(?:webos|android)/)||c.match(/mac|win|linux/)||["other"])[0]},Features:{xpath:!!(k.evaluate),air:!!(i.runtime),query:!!(k.querySelector),json:!!(i.JSON)},Plugins:{}}; -o[o.name]=true;o[o.name+parseInt(o.version,10)]=true;o.Platform[o.Platform.name]=true;o.Request=(function(){var q=function(){return new XMLHttpRequest(); -};var p=function(){return new ActiveXObject("MSXML2.XMLHTTP");};var e=function(){return new ActiveXObject("Microsoft.XMLHTTP");};return Function.attempt(function(){q(); -return q;},function(){p();return p;},function(){e();return e;});})();o.Features.xhr=!!(o.Request);var h=(Function.attempt(function(){return navigator.plugins["Shockwave Flash"].description; -},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");})||"0 r0").match(/\d+/g);o.Plugins.Flash={version:Number(h[0]||"0."+h[1])||0,build:Number(h[2])||0}; -o.exec=function(p){if(!p){return p;}if(i.execScript){i.execScript(p);}else{var e=k.createElement("script");e.setAttribute("type","text/javascript");e.text=p; -k.head.appendChild(e);k.head.removeChild(e);}return p;};String.implement("stripScripts",function(p){var e="";var q=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(r,s){e+=s+"\n"; -return"";});if(p===true){o.exec(e);}else{if(typeOf(p)=="function"){p(e,q);}}return q;});o.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event}); -this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,p){i[e]=p;});this.Document=k.$constructor=new Type("Document",function(){}); -k.$family=Function.from("document").hide();Document.mirror(function(e,p){k[e]=p;});k.html=k.documentElement;if(!k.head){k.head=k.getElementsByTagName("head")[0]; -}if(k.execCommand){try{k.execCommand("BackgroundImageCache",false,true);}catch(g){}}if(this.attachEvent&&!this.addEventListener){var d=function(){this.detachEvent("onunload",d); -k.head=k.html=k.window=null;};this.attachEvent("onunload",d);}var m=Array.from;try{m(k.html.childNodes);}catch(g){Array.from=function(p){if(typeof p!="string"&&Type.isEnumerable(p)&&typeOf(p)!="array"){var e=p.length,q=new Array(e); -while(e--){q[e]=p[e];}return q;}return m(p);};var l=Array.prototype,n=l.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var p=l[e]; -Array[e]=function(q){return p.apply(Array.from(q),n.call(arguments,1));};});}})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window; +break;default:f=g+"="+encodeURIComponent(h);}if(h!=null){d.push(f);}});return d.join("&");}});})();(function(){var f=this.document;var d=f.window=this; +var a=function(k,e){k=k.toLowerCase();e=(e?e.toLowerCase():"");var l=k.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/)||[null,"unknown",0]; +if(l[1]=="trident"){l[1]="ie";if(l[4]){l[2]=l[4];}}else{if(l[1]=="crios"){l[1]="chrome";}}var e=k.match(/ip(?:ad|od|hone)/)?"ios":(k.match(/(?:webos|android)/)||e.match(/mac|win|linux/)||["other"])[0]; +if(e=="win"){e="windows";}return{extend:Function.prototype.extend,name:(l[1]=="version")?l[3]:l[1],version:parseFloat((l[1]=="opera"&&l[4])?l[4]:l[2]),platform:e}; +};var j=this.Browser=a(navigator.userAgent,navigator.platform);if(j.ie){j.version=f.documentMode;}j.extend({Features:{xpath:!!(f.evaluate),air:!!(d.runtime),query:!!(f.querySelector),json:!!(d.JSON)},parseUA:a}); +j.Request=(function(){var l=function(){return new XMLHttpRequest();};var k=function(){return new ActiveXObject("MSXML2.XMLHTTP");};var e=function(){return new ActiveXObject("Microsoft.XMLHTTP"); +};return Function.attempt(function(){l();return l;},function(){k();return k;},function(){e();return e;});})();j.Features.xhr=!!(j.Request);j.exec=function(k){if(!k){return k; +}if(d.execScript){d.execScript(k);}else{var e=f.createElement("script");e.setAttribute("type","text/javascript");e.text=k;f.head.appendChild(e);f.head.removeChild(e); +}return k;};String.implement("stripScripts",function(k){var e="";var l=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(m,n){e+=n+"\n";return""; +});if(k===true){j.exec(e);}else{if(typeOf(k)=="function"){k(e,l);}}return l;});j.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event}); +this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,k){d[e]=k;});this.Document=f.$constructor=new Type("Document",function(){}); +f.$family=Function.from("document").hide();Document.mirror(function(e,k){f[e]=k;});f.html=f.documentElement;if(!f.head){f.head=f.getElementsByTagName("head")[0]; +}if(f.execCommand){try{f.execCommand("BackgroundImageCache",false,true);}catch(c){}}if(this.attachEvent&&!this.addEventListener){var b=function(){this.detachEvent("onunload",b); +f.head=f.html=f.window=null;};this.attachEvent("onunload",b);}var g=Array.from;try{g(f.html.childNodes);}catch(c){Array.from=function(k){if(typeof k!="string"&&Type.isEnumerable(k)&&typeOf(k)!="array"){var e=k.length,l=new Array(e); +while(e--){l[e]=k[e];}return l;}return g(k);};var h=Array.prototype,i=h.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var k=h[e]; +Array[e]=function(l){return k.apply(Array.from(l),i.call(arguments,1));};});}})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window; }c=c||g.event;if(c.$extended){return c;}this.event=c;this.$extended=true;this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey; var i=this.type=c.type;var h=c.target||c.srcElement;while(h&&h.nodeType==3){h=h.parentNode;}this.target=document.id(h);if(i.indexOf("key")==0){var d=this.code=(c.which||c.keyCode); -this.key=b[d];if(i=="keydown"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase(); +this.key=b[d];if(i=="keydown"||i=="keyup"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase(); }}else{if(i=="click"||i=="dblclick"||i=="contextmenu"||i=="DOMMouseScroll"||i.indexOf("mouse")==0){var j=g.document;j=(!j.compatMode||j.compatMode=="CSS1Compat")?j.html:j.body; this.page={x:(c.pageX!=null)?c.pageX:c.clientX+j.scrollLeft,y:(c.pageY!=null)?c.pageY:c.clientY+j.scrollTop};this.client={x:(c.pageX!=null)?c.pageX-g.pageXOffset:c.clientX,y:(c.pageY!=null)?c.pageY-g.pageYOffset:c.clientY}; if(i=="DOMMouseScroll"||i=="mousewheel"){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3;}this.rightClick=(c.which==3||c.button==2);if(i=="mouseover"||i=="mouseout"){var k=c.relatedTarget||c[(i=="mouseover"?"from":"to")+"Element"]; @@ -138,32 +140,32 @@ case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}i };}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o); };d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var k={},m={},d=Object.prototype.toString; k.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};k.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(d.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML"); -};k.setDocument=function(x){var u=x.nodeType;if(u==9){}else{if(u){x=x.ownerDocument;}else{if(x.navigator){x=x.document;}else{return;}}}if(this.document===x){return; -}this.document=x;var z=x.documentElement,v=this.getUIDXML(z),p=m[v],B;if(p){for(B in p){this[B]=p[B];}return;}p=m[v]={};p.root=z;p.isXMLDocument=this.isXML(x); -p.brokenStarGEBTN=p.starSelectsClosedQSA=p.idGetsName=p.brokenMixedCaseQSA=p.brokenGEBCN=p.brokenCheckedQSA=p.brokenEmptyAttributeQSA=p.isHTMLDocument=p.nativeMatchesSelector=false; -var n,o,y,r,s;var t,c="slick_uniqueid";var A=x.createElement("div");var q=x.body||x.getElementsByTagName("body")[0]||z;q.appendChild(A);try{A.innerHTML='<a id="'+c+'"></a>'; -p.isHTMLDocument=!!x.getElementById(c);}catch(w){}if(p.isHTMLDocument){A.style.display="none";A.appendChild(x.createComment(""));o=(A.getElementsByTagName("*").length>1); -try{A.innerHTML="foo</foo>";t=A.getElementsByTagName("*");n=(t&&!!t.length&&t[0].nodeName.charAt(0)=="/");}catch(w){}p.brokenStarGEBTN=o||n;try{A.innerHTML='<a name="'+c+'"></a><b id="'+c+'"></b>'; -p.idGetsName=x.getElementById(c)===A.firstChild;}catch(w){}if(A.getElementsByClassName){try{A.innerHTML='<a class="f"></a><a class="b"></a>';A.getElementsByClassName("b").length; -A.firstChild.className="b";r=(A.getElementsByClassName("b").length!=2);}catch(w){}try{A.innerHTML='<a class="a"></a><a class="f b a"></a>';y=(A.getElementsByClassName("a").length!=2); -}catch(w){}p.brokenGEBCN=r||y;}if(A.querySelectorAll){try{A.innerHTML="foo</foo>";t=A.querySelectorAll("*");p.starSelectsClosedQSA=(t&&!!t.length&&t[0].nodeName.charAt(0)=="/"); -}catch(w){}try{A.innerHTML='<a class="MiX"></a>';p.brokenMixedCaseQSA=!A.querySelectorAll(".MiX").length;}catch(w){}try{A.innerHTML='<select><option selected="selected">a</option></select>'; -p.brokenCheckedQSA=(A.querySelectorAll(":checked").length==0);}catch(w){}try{A.innerHTML='<a class=""></a>';p.brokenEmptyAttributeQSA=(A.querySelectorAll('[class*=""]').length!=0); -}catch(w){}}try{A.innerHTML='<form action="s"><input id="action"/></form>';s=(A.firstChild.getAttribute("action")!="s");}catch(w){}p.nativeMatchesSelector=z.matchesSelector||z.mozMatchesSelector||z.webkitMatchesSelector; -if(p.nativeMatchesSelector){try{p.nativeMatchesSelector.call(z,":slick");p.nativeMatchesSelector=null;}catch(w){}}}try{z.slick_expando=1;delete z.slick_expando; -p.getUID=this.getUIDHTML;}catch(w){p.getUID=this.getUIDXML;}q.removeChild(A);A=t=q=null;p.getAttribute=(p.isHTMLDocument&&s)?function(E,C){var F=this.attributeGetters[C]; -if(F){return F.call(E);}var D=E.getAttributeNode(C);return(D)?D.nodeValue:null;}:function(D,C){var E=this.attributeGetters[C];return(E)?E.call(D):D.getAttribute(C); -};p.hasAttribute=(z&&this.isNativeCode(z.hasAttribute))?function(D,C){return D.hasAttribute(C);}:function(D,C){D=D.getAttributeNode(C);return !!(D&&(D.specified||D.nodeValue)); -};p.contains=(z&&this.isNativeCode(z.contains))?function(C,D){return C.contains(D);}:(z&&z.compareDocumentPosition)?function(C,D){return C===D||!!(C.compareDocumentPosition(D)&16); -}:function(C,D){if(D){do{if(D===C){return true;}}while((D=D.parentNode));}return false;};p.documentSorter=(z.compareDocumentPosition)?function(D,C){if(!D.compareDocumentPosition||!C.compareDocumentPosition){return 0; -}return D.compareDocumentPosition(C)&4?-1:D===C?0:1;}:("sourceIndex" in z)?function(D,C){if(!D.sourceIndex||!C.sourceIndex){return 0;}return D.sourceIndex-C.sourceIndex; -}:(x.createRange)?function(F,D){if(!F.ownerDocument||!D.ownerDocument){return 0;}var E=F.ownerDocument.createRange(),C=D.ownerDocument.createRange();E.setStart(F,0); -E.setEnd(F,0);C.setStart(D,0);C.setEnd(D,0);return E.compareBoundaryPoints(Range.START_TO_END,C);}:null;z=null;for(B in p){this[B]=p[B];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={}; -k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]);if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9); -if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U);}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f); -simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors;}E=U.getElementsByTagName(v);if(s){return E[0]||null; -}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors;}A=U.getElementById(v); -if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A); +};k.setDocument=function(w){var p=w.nodeType;if(p==9){}else{if(p){w=w.ownerDocument;}else{if(w.navigator){w=w.document;}else{return;}}}if(this.document===w){return; +}this.document=w;var A=w.documentElement,o=this.getUIDXML(A),s=m[o],r;if(s){for(r in s){this[r]=s[r];}return;}s=m[o]={};s.root=A;s.isXMLDocument=this.isXML(w); +s.brokenStarGEBTN=s.starSelectsClosedQSA=s.idGetsName=s.brokenMixedCaseQSA=s.brokenGEBCN=s.brokenCheckedQSA=s.brokenEmptyAttributeQSA=s.isHTMLDocument=s.nativeMatchesSelector=false; +var q,u,y,z,t;var x,v="slick_uniqueid";var c=w.createElement("div");var n=w.body||w.getElementsByTagName("body")[0]||A;n.appendChild(c);try{c.innerHTML='<a id="'+v+'"></a>'; +s.isHTMLDocument=!!w.getElementById(v);}catch(C){}if(s.isHTMLDocument){c.style.display="none";c.appendChild(w.createComment(""));u=(c.getElementsByTagName("*").length>1); +try{c.innerHTML="foo</foo>";x=c.getElementsByTagName("*");q=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");}catch(C){}s.brokenStarGEBTN=u||q;try{c.innerHTML='<a name="'+v+'"></a><b id="'+v+'"></b>'; +s.idGetsName=w.getElementById(v)===c.firstChild;}catch(C){}if(c.getElementsByClassName){try{c.innerHTML='<a class="f"></a><a class="b"></a>';c.getElementsByClassName("b").length; +c.firstChild.className="b";z=(c.getElementsByClassName("b").length!=2);}catch(C){}try{c.innerHTML='<a class="a"></a><a class="f b a"></a>';y=(c.getElementsByClassName("a").length!=2); +}catch(C){}s.brokenGEBCN=z||y;}if(c.querySelectorAll){try{c.innerHTML="foo</foo>";x=c.querySelectorAll("*");s.starSelectsClosedQSA=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/"); +}catch(C){}try{c.innerHTML='<a class="MiX"></a>';s.brokenMixedCaseQSA=!c.querySelectorAll(".MiX").length;}catch(C){}try{c.innerHTML='<select><option selected="selected">a</option></select>'; +s.brokenCheckedQSA=(c.querySelectorAll(":checked").length==0);}catch(C){}try{c.innerHTML='<a class=""></a>';s.brokenEmptyAttributeQSA=(c.querySelectorAll('[class*=""]').length!=0); +}catch(C){}}try{c.innerHTML='<form action="s"><input id="action"/></form>';t=(c.firstChild.getAttribute("action")!="s");}catch(C){}s.nativeMatchesSelector=A.matches||A.mozMatchesSelector||A.webkitMatchesSelector; +if(s.nativeMatchesSelector){try{s.nativeMatchesSelector.call(A,":slick");s.nativeMatchesSelector=null;}catch(C){}}}try{A.slick_expando=1;delete A.slick_expando; +s.getUID=this.getUIDHTML;}catch(C){s.getUID=this.getUIDXML;}n.removeChild(c);c=x=n=null;s.getAttribute=(s.isHTMLDocument&&t)?function(G,E){var H=this.attributeGetters[E]; +if(H){return H.call(G);}var F=G.getAttributeNode(E);return(F)?F.nodeValue:null;}:function(F,E){var G=this.attributeGetters[E];return(G)?G.call(F):F.getAttribute(E); +};s.hasAttribute=(A&&this.isNativeCode(A.hasAttribute))?function(F,E){return F.hasAttribute(E);}:function(F,E){F=F.getAttributeNode(E);return !!(F&&(F.specified||F.nodeValue)); +};var D=A&&this.isNativeCode(A.contains),B=w&&this.isNativeCode(w.contains);s.contains=(D&&B)?function(E,F){return E.contains(F);}:(D&&!B)?function(E,F){return E===F||((E===w)?w.documentElement:E).contains(F); +}:(A&&A.compareDocumentPosition)?function(E,F){return E===F||!!(E.compareDocumentPosition(F)&16);}:function(E,F){if(F){do{if(F===E){return true;}}while((F=F.parentNode)); +}return false;};s.documentSorter=(A.compareDocumentPosition)?function(F,E){if(!F.compareDocumentPosition||!E.compareDocumentPosition){return 0;}return F.compareDocumentPosition(E)&4?-1:F===E?0:1; +}:("sourceIndex" in A)?function(F,E){if(!F.sourceIndex||!E.sourceIndex){return 0;}return F.sourceIndex-E.sourceIndex;}:(w.createRange)?function(H,F){if(!H.ownerDocument||!F.ownerDocument){return 0; +}var G=H.ownerDocument.createRange(),E=F.ownerDocument.createRange();G.setStart(H,0);G.setEnd(H,0);E.setStart(F,0);E.setEnd(F,0);return G.compareBoundaryPoints(Range.START_TO_END,E); +}:null;A=null;for(r in s){this[r]=s[r];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={};k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]); +if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9);if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U); +}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f);simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors; +}E=U.getElementsByTagName(v);if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors; +}A=U.getElementById(v);if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A); }}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v); if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+e.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*"); for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p); @@ -191,7 +193,7 @@ k.matchNode=function(n,o){if(this.isHTMLDocument&&this.nativeMatchesSelector){tr if(this.matchSelector(n,(this.isXMLDocument)?p.tag:p.tag.toUpperCase(),p.id,p.classes,p.attributes,p.pseudos)){return true;}s++;}}if(s==t.length){return false; }var c=this.search(this.document,t),v;for(q=0;v=c[q++];){if(v===n){return true;}}return false;};k.matchPseudo=function(q,c,p){var n="pseudo:"+c;if(this[n]){return this[n](q,p); }var o=this.getAttribute(q,c);return(p)?p==o:!!o;};k.matchSelector=function(o,v,c,p,q,s){if(v){var t=(this.isXMLDocument)?o.nodeName:o.nodeName.toUpperCase(); -if(v=="*"){if(t<"@"){return false;}}else{if(t!=v){return false;}}}if(c&&o.getAttribute("id")!=c){return false;}var r,n,u;if(p){for(r=p.length;r--;){u=o.getAttribute("class")||o.className; +if(v=="*"){if(t<"@"){return false;}}else{if(t!=v){return false;}}}if(c&&o.getAttribute("id")!=c){return false;}var r,n,u;if(p){for(r=p.length;r--;){u=this.getAttribute(o,"class"); if(!(u&&p[r].regexp.test(u))){return false;}}}if(q){for(r=q.length;r--;){n=q[r];if(n.operator?!n.test(this.getAttribute(o,n.key)):!this.hasAttribute(o,n.key)){return false; }}}if(s){for(r=s.length;r--;){n=s[r];if(!this.matchPseudo(o,n.key,n.value)){return false;}}}return true;};var j={" ":function(q,w,n,r,s,u,p){var t,v,o; if(this.isHTMLDocument){getById:if(n){v=this.document.getElementById(n);if((!v&&q.all)||(this.idGetsName&&v&&v.getAttributeNode("id").nodeValue!=n)){o=q.all[n]; @@ -209,28 +211,29 @@ break;}}},"!^":function(p,c,r,o,n,q){p=p.lastChild;if(p){if(p.nodeType==1){this. return !(n&&n.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,n){return !this.matchNode(c,n);},contains:function(c,n){return(c.innerText||c.textContent||"").indexOf(n)>-1; },"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false; }}return true;},"only-child":function(o){var n=o;while((n=n.previousSibling)){if(n.nodeType==1){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeType==1){return false; -}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+c+1); +}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+(c+1)); },even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var n=c.nodeName; while((c=c.previousSibling)){if(c.nodeName==n){return false;}}return true;},"last-of-type":function(c){var n=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==n){return false; }}return true;},"only-of-type":function(o){var n=o,p=o.nodeName;while((n=n.previousSibling)){if(n.nodeName==p){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeName==p){return false; }}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex")); -},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"class":function(){return this.getAttribute("class")||this.className; -},"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for");},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href"); -},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style");},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null; -},type:function(){return this.getAttribute("type");},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null; -}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{});e.version="1.1.6";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true); -};e.contains=function(c,n){k.setDocument(c);return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n); -return k.hasAttribute(n,c);};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n; +},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for"); +},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href");},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style"); +},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null;},type:function(){return this.getAttribute("type"); +},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null;}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{}); +e.version="1.1.7";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true);};e.contains=function(c,n){k.setDocument(c); +return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n);return k.hasAttribute(n,c); +};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n; return this;};e.lookupAttributeGetter=function(c){return k.attributeGetters[c];};e.definePseudo=function(c,n){k["pseudo:"+c]=function(p,o){return n.call(p,o); };return this;};e.lookupPseudo=function(c){var n=k["pseudo:"+c];if(n){return function(o){return n.call(this,o);};}return null;};e.override=function(n,c){k.override(n,c); return this;};e.isXML=k.isXML;e.uidOf=function(c){return k.getUIDHTML(c);};if(!this.Slick){this.Slick=e;}}).apply((typeof exports!="undefined")?exports:this); -var Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={};}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0]; -b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length;f<c;f++){a=d[f];if(g[a.key]!=null){continue; -}if(a.value!=null&&a.operator=="="){g[a.key]=a.value;}else{if(!a.value&&!a.operator){g[a.key]=true;}}}}if(e.classList&&g["class"]==null){g["class"]=e.classList.join(" "); -}}return document.newElement(b,g);};if(Browser.Element){Element.prototype=Browser.Element.prototype;}new Type("Element",Element).mirror(function(a){if(Array.prototype[a]){return; -}var b={};b[a]=function(){var h=[],e=arguments,j=true;for(var g=0,d=this.length;g<d;g++){var f=this[g],c=h[g]=f[a].apply(f,e);j=(j&&typeOf(c)=="element"); -}return(j)?new Elements(h):h;};Elements.implement(b);});if(!Browser.Element){Element.parent=Object;Element.Prototype={"$family":Function.from("element").hide()}; -Element.mirror(function(a,b){Element.Prototype[a]=b;});}Element.Constructors={};var IFrame=new Type("IFrame",function(){var e=Array.link(arguments,{properties:Type.isObject,iframe:function(f){return(f!=null); +var Element=this.Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={}; +}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0];b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length; +f<c;f++){a=d[f];if(g[a.key]!=null){continue;}if(a.value!=null&&a.operator=="="){g[a.key]=a.value;}else{if(!a.value&&!a.operator){g[a.key]=true;}}}}if(e.classList&&g["class"]==null){g["class"]=e.classList.join(" "); +}}return document.newElement(b,g);};if(Browser.Element){Element.prototype=Browser.Element.prototype;Element.prototype._fireEvent=(function(a){return function(b,c){return a.call(this,b,c); +};})(Element.prototype.fireEvent);}new Type("Element",Element).mirror(function(a){if(Array.prototype[a]){return;}var b={};b[a]=function(){var h=[],e=arguments,j=true; +for(var g=0,d=this.length;g<d;g++){var f=this[g],c=h[g]=f[a].apply(f,e);j=(j&&typeOf(c)=="element");}return(j)?new Elements(h):h;};Elements.implement(b); +});if(!Browser.Element){Element.parent=Object;Element.Prototype={"$constructor":Element,"$family":Function.from("element").hide()};Element.mirror(function(a,b){Element.Prototype[a]=b; +});}Element.Constructors={};var IFrame=new Type("IFrame",function(){var e=Array.link(arguments,{properties:Type.isObject,iframe:function(f){return(f!=null); }});var c=e.properties||{},b;if(e.iframe){b=document.id(e.iframe);}var d=c.onload||function(){};delete c.onload;c.id=c.name=[c.id,c.name,b?(b.id||b.name):"IFrame_"+String.uniqueID()].pick(); b=new Element(b||"iframe",c);var a=function(){d.call(b.contentWindow);};if(window.frames[c.id]){a();}else{b.addListener("load",a);}return b;});var Elements=this.Elements=function(a){if(a&&a.length){var e={},d; for(var c=0;d=a[c++];){var b=Slick.uidOf(d);if(!e[b]){e[b]=true;this.push(d);}}}};Elements.prototype={length:0};Elements.parent=Array;new Type("Elements",Elements).implement({filter:function(a,b){if(!a){return this; @@ -238,101 +241,119 @@ for(var c=0;d=a[c++];){var b=Slick.uidOf(d);if(!e[b]){e[b]=true;this.push(d);}}} b<a;b++){var c=document.id(arguments[b]);if(c){this[d++]=c;}}return(this.length=d);}.protect(),unshift:function(){var b=[];for(var c=0,a=arguments.length; c<a;c++){var d=document.id(arguments[c]);if(d){b.push(d);}}return Array.prototype.unshift.apply(this,b);}.protect(),concat:function(){var b=new Elements(this); for(var c=0,a=arguments.length;c<a;c++){var d=arguments[c];if(Type.isEnumerable(d)){b.append(d);}else{b.push(d);}}return b;}.protect(),append:function(c){for(var b=0,a=c.length; -b<a;b++){this.push(c[b]);}return this;}.protect(),empty:function(){while(this.length){delete this[--this.length];}return this;}.protect()});(function(){var g=Array.prototype.splice,b={"0":0,"1":1,length:2}; -g.call(b,1,1);if(b[1]==1){Elements.implement("splice",function(){var h=this.length;var e=g.apply(this,arguments);while(h>=this.length){delete this[h--]; -}return e;}.protect());}Elements.implement(Array.prototype);Array.mirror(Elements);var f;try{var a=document.createElement("<input name=x>");f=(a.name=="x"); -}catch(c){}var d=function(e){return(""+e).replace(/&/g,"&").replace(/"/g,""");};Document.implement({newElement:function(e,h){if(h&&h.checked!=null){h.defaultChecked=h.checked; -}if(f&&h){e="<"+e;if(h.name){e+=' name="'+d(h.name)+'"';}if(h.type){e+=' type="'+d(h.type)+'"';}e+=">";delete h.name;delete h.type;}return this.id(this.createElement(e)).set(h); -}});})();Document.implement({newTextNode:function(a){return this.createTextNode(a);},getDocument:function(){return this;},getWindow:function(){return this.window; -},id:(function(){var a={string:function(d,c,b){d=Slick.find(b,"#"+d.replace(/(\W)/g,"\\$1"));return(d)?a.element(d,c):null;},element:function(b,c){$uid(b); -if(!c&&!b.$family&&!(/^(?:object|embed)$/i).test(b.tagName)){Object.append(b,Element.Prototype);}return b;},object:function(c,d,b){if(c.toElement){return a.element(c.toElement(b),d); -}return null;}};a.textnode=a.whitespace=a.window=a.document=function(b){return b;};return function(c,e,d){if(c&&c.$family&&c.uid){return c;}var b=typeOf(c); -return(a[b])?a[b](c,e,d||document):null;};})()});if(window.$==null){Window.implement("$",function(a,b){return document.id(a,b,this.document);});}Window.implement({getDocument:function(){return this.document; -},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(a){return Slick.search(this,a,new Elements);},getElement:function(a){return document.id(Slick.find(this,a)); -}});var contains={contains:function(a){return Slick.contains(this,a);}};if(!document.contains){Document.implement(contains);}if(!document.createElement("div").contains){Element.implement(contains); -}var injectCombinator=function(d,c){if(!d){return c;}d=Object.clone(Slick.parse(d));var b=d.expressions;for(var a=b.length;a--;){b[a][0].combinator=c;}return d; -};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(a,b){Element.implement(b,function(c){return this.getElement(injectCombinator(c,a)); -});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(a,b){Element.implement(b,function(c){return this.getElements(injectCombinator(c,a)); -});});Element.implement({getFirst:function(a){return document.id(Slick.search(this,injectCombinator(a,">"))[0]);},getLast:function(a){return document.id(Slick.search(this,injectCombinator(a,">")).getLast()); -},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(a){return document.id(Slick.find(this,"#"+(""+a).replace(/(\W)/g,"\\$1"))); -},match:function(a){return !a||Slick.match(this,a);}});if(window.$$==null){Window.implement("$$",function(a){if(arguments.length==1){if(typeof a=="string"){return Slick.search(this.document,a,new Elements); -}else{if(Type.isEnumerable(a)){return new Elements(a);}}}return new Elements(arguments);});}(function(){var b={before:function(n,m){var o=m.parentNode; -if(o){o.insertBefore(n,m);}},after:function(n,m){var o=m.parentNode;if(o){o.insertBefore(n,m.nextSibling);}},bottom:function(n,m){m.appendChild(n);},top:function(n,m){m.insertBefore(n,m.firstChild); -}};b.inside=b.bottom;var k={},d={};var i={};Array.forEach(["type","value","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","readOnly","rowSpan","tabIndex","useMap"],function(m){i[m.toLowerCase()]=m; -});Object.append(i,{html:"innerHTML",text:(function(){var m=document.createElement("div");return(m.textContent==null)?"innerText":"textContent";})()}); -Object.forEach(i,function(n,m){d[m]=function(o,p){o[n]=p;};k[m]=function(o){return o[n];};});var a=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked","autofocus","controls","autoplay","loop"]; -var h={};Array.forEach(a,function(m){var n=m.toLowerCase();h[n]=m;d[n]=function(o,p){o[m]=!!p;};k[n]=function(o){return !!o[m];};});Object.append(d,{"class":function(m,n){("className" in m)?m.className=n:m.setAttribute("class",n); -},"for":function(m,n){("htmlFor" in m)?m.htmlFor=n:m.setAttribute("for",n);},style:function(m,n){(m.style)?m.style.cssText=n:m.setAttribute("style",n); -}});Element.implement({setProperty:function(n,o){var m=n.toLowerCase();if(o==null){if(!h[m]){this.removeAttribute(n);return this;}o=false;}var p=d[m];if(p){p(this,o); -}else{this.setAttribute(n,o);}return this;},setProperties:function(m){for(var n in m){this.setProperty(n,m[n]);}return this;},getProperty:function(o){var n=k[o.toLowerCase()]; -if(n){return n(this);}var m=Slick.getAttribute(this,o);return(!m&&!Slick.hasAttribute(this,o))?null:m;},getProperties:function(){var m=Array.from(arguments); -return m.map(this.getProperty,this).associate(m);},removeProperty:function(m){return this.setProperty(m,null);},removeProperties:function(){Array.each(arguments,this.removeProperty,this); -return this;},set:function(o,n){var m=Element.Properties[o];(m&&m.set)?m.set.call(this,n):this.setProperty(o,n);}.overloadSetter(),get:function(n){var m=Element.Properties[n]; -return(m&&m.get)?m.get.apply(this):this.getProperty(n);}.overloadGetter(),erase:function(n){var m=Element.Properties[n];(m&&m.erase)?m.erase.apply(this):this.removeProperty(n); -return this;},hasClass:function(m){return this.className.clean().contains(m," ");},addClass:function(m){if(!this.hasClass(m)){this.className=(this.className+" "+m).clean(); -}return this;},removeClass:function(m){this.className=this.className.replace(new RegExp("(^|\\s)"+m+"(?:\\s|$)"),"$1");return this;},toggleClass:function(m,n){if(n==null){n=!this.hasClass(m); -}return(n)?this.addClass(m):this.removeClass(m);},adopt:function(){var p=this,m,r=Array.flatten(arguments),q=r.length;if(q>1){p=m=document.createDocumentFragment(); -}for(var o=0;o<q;o++){var n=document.id(r[o],true);if(n){p.appendChild(n);}}if(m){this.appendChild(m);}return this;},appendText:function(n,m){return this.grab(this.getDocument().newTextNode(n),m); -},grab:function(n,m){b[m||"bottom"](document.id(n,true),this);return this;},inject:function(n,m){b[m||"bottom"](this,document.id(n,true));return this;},replaces:function(m){m=document.id(m,true); -m.parentNode.replaceChild(this,m);return this;},wraps:function(n,m){n=document.id(n,true);return this.replaces(n).grab(n,m);},getSelected:function(){this.selectedIndex; -return new Elements(Array.from(this.options).filter(function(m){return m.selected;}));},toQueryString:function(){var m=[];this.getElements("input, select, textarea").each(function(o){var n=o.type; -if(!o.name||o.disabled||n=="submit"||n=="reset"||n=="file"||n=="image"){return;}var p=(o.get("tag")=="select")?o.getSelected().map(function(q){return document.id(q).get("value"); -}):((n=="radio"||n=="checkbox")&&!o.checked)?null:o.get("value");Array.from(p).each(function(q){if(typeof q!="undefined"){m.push(encodeURIComponent(o.name)+"="+encodeURIComponent(q)); -}});});return m.join("&");}});var j={},e={};var c=function(m){return(e[m]||(e[m]={}));};var g=function(n){var m=n.uid;if(n.removeEvents){n.removeEvents(); -}if(n.clearAttributes){n.clearAttributes();}if(m!=null){delete j[m];delete e[m];}return n;};var l={input:"checked",option:"selected",textarea:"value"}; -Element.implement({destroy:function(){var m=g(this).getElementsByTagName("*");Array.each(m,g);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose); -return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},clone:function(r,p){r=r!==false;var w=this.cloneNode(r),o=[w],q=[this],u; -if(r){o.append(Array.from(w.getElementsByTagName("*")));q.append(Array.from(this.getElementsByTagName("*")));}for(u=o.length;u--;){var s=o[u],v=q[u];if(!p){s.removeAttribute("id"); -}if(s.clearAttributes){s.clearAttributes();s.mergeAttributes(v);s.removeAttribute("uid");if(s.options){var z=s.options,m=v.options;for(var t=z.length;t--; -){z[t].selected=m[t].selected;}}}var n=l[v.tagName.toLowerCase()];if(n&&v[n]){s[n]=v[n];}}if(Browser.ie){var x=w.getElementsByTagName("object"),y=this.getElementsByTagName("object"); -for(u=x.length;u--;){x[u].outerHTML=y[u].outerHTML;}}return document.id(w);}});[Element,Window,Document].invoke("implement",{addListener:function(p,o){if(p=="unload"){var m=o,n=this; -o=function(){n.removeListener("unload",o);m();};}else{j[$uid(this)]=this;}if(this.addEventListener){this.addEventListener(p,o,!!arguments[2]);}else{this.attachEvent("on"+p,o); -}return this;},removeListener:function(n,m){if(this.removeEventListener){this.removeEventListener(n,m,!!arguments[2]);}else{this.detachEvent("on"+n,m); -}return this;},retrieve:function(n,m){var p=c($uid(this)),o=p[n];if(m!=null&&o==null){o=p[n]=m;}return o!=null?o:null;},store:function(n,m){var o=c($uid(this)); -o[n]=m;return this;},eliminate:function(m){var n=c($uid(this));delete n[m];return this;}});if(window.attachEvent&&!window.addEventListener){window.addListener("unload",function(){Object.each(j,g); -if(window.CollectGarbage){CollectGarbage();}});}Element.Properties={};Element.Properties.style={set:function(m){this.style.cssText=m;},get:function(){return this.style.cssText; -},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();}};Element.Properties.html=(function(){var s=Function.attempt(function(){var u=document.createElement("table"); -u.innerHTML="<tr><td></td></tr>";});var t=document.createElement("div");var o={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]}; -o.thead=o.tfoot=o.tbody;t.innerHTML="<nav></nav>";var n=t.childNodes.length==1;if(!n){var q="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),p=document.createDocumentFragment(),m=q.length; -while(m--){p.createElement(q[m]);}p.appendChild(t);}var r={set:function(v){if(typeOf(v)=="array"){v=v.join("");}var w=(!s&&o[this.get("tag")]);if(!w&&!n){w=[0,"",""]; -}if(w){var x=t;x.innerHTML=w[1]+v+w[2];for(var u=w[0];u--;){x=x.firstChild;}this.empty().adopt(x.childNodes);}else{this.innerHTML=v;}}};r.erase=r.set;return r; -})();var f=document.createElement("form");f.innerHTML="<select><option>s</option></select>";if(f.firstChild.value!="s"){Element.Properties.value={set:function(r){var n=this.get("tag"); -if(n!="select"){return this.setProperty("value",r);}var o=this.getElements("option");for(var p=0;p<o.length;p++){var q=o[p],m=q.getAttributeNode("value"),s=(m&&m.specified)?q.value:q.get("text"); -if(s==r){return q.selected=true;}}},get:function(){var o=this,n=o.get("tag");if(n!="select"&&n!="option"){return this.getProperty("value");}if(n=="select"&&!(o=o.getSelected()[0])){return""; -}var m=o.getAttributeNode("value");return(m&&m.specified)?o.value:o.get("text");}};}})();(function(){var f=document.html;Element.Properties.styles={set:function(i){this.setStyles(i); -}};var h=(f.style.opacity!=null),a=(f.style.filter!=null),g=/alpha\(opacity=([\d.]+)\)/i;var b=function(j,i){j.store("$opacity",i);j.style.visibility=i>0?"visible":"hidden"; -};var d=(h?function(j,i){j.style.opacity=i;}:(a?function(j,i){if(!j.currentStyle||!j.currentStyle.hasLayout){j.style.zoom=1;}i=(i*100).limit(0,100).round(); -i=(i==100)?"":"alpha(opacity="+i+")";var k=j.style.filter||j.getComputedStyle("filter")||"";j.style.filter=g.test(k)?k.replace(g,i):k+i;}:b));var e=(h?function(j){var i=j.style.opacity||j.getComputedStyle("opacity"); -return(i=="")?1:i.toFloat();}:(a?function(j){var k=(j.style.filter||j.getComputedStyle("filter")),i;if(k){i=k.match(g);}return(i==null||k==null)?1:(i[1]/100); -}:function(j){var i=j.retrieve("$opacity");if(i==null){i=(j.style.visibility=="hidden"?0:1);}return i;}));var c=(f.style.cssFloat==null)?"styleFloat":"cssFloat"; -Element.implement({getComputedStyle:function(k){if(this.currentStyle){return this.currentStyle[k.camelCase()];}var j=Element.getDocument(this).defaultView,i=j?j.getComputedStyle(this,null):null; -return(i)?i.getPropertyValue((k==c)?"float":k.hyphenate()):null;},setStyle:function(j,i){if(j=="opacity"){d(this,parseFloat(i));return this;}j=(j=="float"?c:j).camelCase(); -if(typeOf(i)!="string"){var k=(Element.Styles[j]||"@").split(" ");i=Array.from(i).map(function(m,l){if(!k[l]){return"";}return(typeOf(m)=="number")?k[l].replace("@",Math.round(m)):m; -}).join(" ");}else{if(i==String(Number(i))){i=Math.round(i);}}this.style[j]=i;return this;},getStyle:function(o){if(o=="opacity"){return e(this);}o=(o=="float"?c:o).camelCase(); -var i=this.style[o];if(!i||o=="zIndex"){i=[];for(var n in Element.ShortStyles){if(o!=n){continue;}for(var m in Element.ShortStyles[n]){i.push(this.getStyle(m)); -}return i.join(" ");}i=this.getComputedStyle(o);}if(i){i=String(i);var k=i.match(/rgba?\([\d\s,]+\)/);if(k){i=i.replace(k[0],k[0].rgbToHex());}}if(Browser.opera||(Browser.ie&&isNaN(parseFloat(i)))){if((/^(height|width)$/).test(o)){var j=(o=="width")?["left","right"]:["top","bottom"],l=0; -j.each(function(p){l+=this.getStyle("border-"+p+"-width").toInt()+this.getStyle("padding-"+p).toInt();},this);return this["offset"+o.capitalize()]-l+"px"; -}if(Browser.opera&&String(i).indexOf("px")!=-1){return i;}if((/^border(.+)Width|margin|padding/).test(o)){return"0px";}}return i;},setStyles:function(j){for(var i in j){this.setStyle(i,j[i]); -}return this;},getStyles:function(){var i={};Array.flatten(arguments).each(function(j){i[j]=this.getStyle(j);},this);return i;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"}; -Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(o){var n=Element.ShortStyles; -var j=Element.Styles;["margin","padding"].each(function(p){var q=p+o;n[p][q]=j[q]="@px";});var m="border"+o;n.border[m]=j[m]="@px @ rgb(@, @, @)";var l=m+"Width",i=m+"Style",k=m+"Color"; -n[m]={};n.borderWidth[l]=n[m][l]=j[l]="@px";n.borderStyle[i]=n[m][i]=j[i]="@";n.borderColor[k]=n[m][k]=j[k]="rgb(@, @, @)";});})();(function(){Element.Properties.events={set:function(b){this.addEvents(b); -}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{});if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this; -}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f);}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k); -}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j);};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow()); -if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]);}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events"); -if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d);if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e]; -if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e);}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this; -},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this;},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]); -}return this;}var c=this.retrieve("events");if(!c){return this;}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e); -},this);delete c[b];}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c); +b<a;b++){this.push(c[b]);}return this;}.protect(),empty:function(){while(this.length){delete this[--this.length];}return this;}.protect()});(function(){var f=Array.prototype.splice,a={"0":0,"1":1,length:2}; +f.call(a,1,1);if(a[1]==1){Elements.implement("splice",function(){var g=this.length;var e=f.apply(this,arguments);while(g>=this.length){delete this[g--]; +}return e;}.protect());}Array.forEachMethod(function(g,e){Elements.implement(e,g);});Array.mirror(Elements);var d;try{d=(document.createElement("<input name=x>").name=="x"); +}catch(b){}var c=function(e){return(""+e).replace(/&/g,"&").replace(/"/g,""");};Document.implement({newElement:function(e,g){if(g&&g.checked!=null){g.defaultChecked=g.checked; +}if(d&&g){e="<"+e;if(g.name){e+=' name="'+c(g.name)+'"';}if(g.type){e+=' type="'+c(g.type)+'"';}e+=">";delete g.name;delete g.type;}return this.id(this.createElement(e)).set(g); +}});})();(function(){Slick.uidOf(window);Slick.uidOf(document);Document.implement({newTextNode:function(e){return this.createTextNode(e);},getDocument:function(){return this; +},getWindow:function(){return this.window;},id:(function(){var e={string:function(L,K,l){L=Slick.find(l,"#"+L.replace(/(\W)/g,"\\$1"));return(L)?e.element(L,K):null; +},element:function(K,L){Slick.uidOf(K);if(!L&&!K.$family&&!(/^(?:object|embed)$/i).test(K.tagName)){var l=K.fireEvent;K._fireEvent=function(M,N){return l(M,N); +};Object.append(K,Element.Prototype);}return K;},object:function(K,L,l){if(K.toElement){return e.element(K.toElement(l),L);}return null;}};e.textnode=e.whitespace=e.window=e.document=function(l){return l; +};return function(K,M,L){if(K&&K.$family&&K.uniqueNumber){return K;}var l=typeOf(K);return(e[l])?e[l](K,M,L||document):null;};})()});if(window.$==null){Window.implement("$",function(e,l){return document.id(e,l,this.document); +});}Window.implement({getDocument:function(){return this.document;},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(e){return Slick.search(this,e,new Elements); +},getElement:function(e){return document.id(Slick.find(this,e));}});var p={contains:function(e){return Slick.contains(this,e);}};if(!document.contains){Document.implement(p); +}if(!document.createElement("div").contains){Element.implement(p);}var v=function(L,K){if(!L){return K;}L=Object.clone(Slick.parse(L));var l=L.expressions; +for(var e=l.length;e--;){l[e][0].combinator=K;}return L;};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(e,l){Element.implement(l,function(K){return this.getElement(v(K,e)); +});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(e,l){Element.implement(l,function(K){return this.getElements(v(K,e)); +});});Element.implement({getFirst:function(e){return document.id(Slick.search(this,v(e,">"))[0]);},getLast:function(e){return document.id(Slick.search(this,v(e,">")).getLast()); +},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(e){return document.id(Slick.find(this,"#"+(""+e).replace(/(\W)/g,"\\$1"))); +},match:function(e){return !e||Slick.match(this,e);}});if(window.$$==null){Window.implement("$$",function(e){if(arguments.length==1){if(typeof e=="string"){return Slick.search(this.document,e,new Elements); +}else{if(Type.isEnumerable(e)){return new Elements(e);}}}return new Elements(arguments);});}var A={before:function(l,e){var K=e.parentNode;if(K){K.insertBefore(l,e); +}},after:function(l,e){var K=e.parentNode;if(K){K.insertBefore(l,e.nextSibling);}},bottom:function(l,e){e.appendChild(l);},top:function(l,e){e.insertBefore(l,e.firstChild); +}};A.inside=A.bottom;var n={},d={};var o={};Array.forEach(["type","value","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","rowSpan","tabIndex","useMap"],function(e){o[e.toLowerCase()]=e; +});o.html="innerHTML";o.text=(document.createElement("div").textContent==null)?"innerText":"textContent";Object.forEach(o,function(l,e){d[e]=function(K,L){K[l]=L; +};n[e]=function(K){return K[l];};});var B=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked","autofocus","controls","autoplay","loop"]; +var k={};Array.forEach(B,function(e){var l=e.toLowerCase();k[l]=e;d[l]=function(K,L){K[e]=!!L;};n[l]=function(K){return !!K[e];};});Object.append(d,{"class":function(e,l){("className" in e)?e.className=(l||""):e.setAttribute("class",l); +},"for":function(e,l){("htmlFor" in e)?e.htmlFor=l:e.setAttribute("for",l);},style:function(e,l){(e.style)?e.style.cssText=l:e.setAttribute("style",l); +},value:function(e,l){e.value=(l!=null)?l:"";}});n["class"]=function(e){return("className" in e)?e.className||null:e.getAttribute("class");};var f=document.createElement("button"); +try{f.type="button";}catch(E){}if(f.type!="button"){d.type=function(e,l){e.setAttribute("type",l);};}f=null;var s=document.createElement("input");s.value="t"; +s.type="submit";if(s.value!="t"){d.type=function(l,e){var K=l.value;l.type=e;l.value=K;};}s=null;var u=(function(e){e.random="attribute";return(e.getAttribute("random")=="attribute"); +})(document.createElement("div"));var i=(function(e){e.innerHTML='<object><param name="should_fix" value="the unknown"></object>';return e.cloneNode(true).firstChild.childNodes.length!=1; +})(document.createElement("div"));var j=!!document.createElement("div").classList;var F=function(e){var l=(e||"").clean().split(" "),K={};return l.filter(function(L){if(L!==""&&!K[L]){return K[L]=L; +}});};var t=function(e){this.classList.add(e);};var g=function(e){this.classList.remove(e);};Element.implement({setProperty:function(l,K){var L=d[l.toLowerCase()]; +if(L){L(this,K);}else{var e;if(u){e=this.retrieve("$attributeWhiteList",{});}if(K==null){this.removeAttribute(l);if(u){delete e[l];}}else{this.setAttribute(l,""+K); +if(u){e[l]=true;}}}return this;},setProperties:function(e){for(var l in e){this.setProperty(l,e[l]);}return this;},getProperty:function(M){var K=n[M.toLowerCase()]; +if(K){return K(this);}if(u){var l=this.getAttributeNode(M),L=this.retrieve("$attributeWhiteList",{});if(!l){return null;}if(l.expando&&!L[M]){var N=this.outerHTML; +if(N.substr(0,N.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(M)<0){return null;}L[M]=true;}}var e=Slick.getAttribute(this,M);return(!e&&!Slick.hasAttribute(this,M))?null:e; +},getProperties:function(){var e=Array.from(arguments);return e.map(this.getProperty,this).associate(e);},removeProperty:function(e){return this.setProperty(e,null); +},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;},set:function(K,l){var e=Element.Properties[K];(e&&e.set)?e.set.call(this,l):this.setProperty(K,l); +}.overloadSetter(),get:function(l){var e=Element.Properties[l];return(e&&e.get)?e.get.apply(this):this.getProperty(l);}.overloadGetter(),erase:function(l){var e=Element.Properties[l]; +(e&&e.erase)?e.erase.apply(this):this.removeProperty(l);return this;},hasClass:j?function(e){return this.classList.contains(e);}:function(e){return this.className.clean().contains(e," "); +},addClass:j?function(e){F(e).forEach(t,this);return this;}:function(e){this.className=F(e+" "+this.className).join(" ");return this;},removeClass:j?function(e){F(e).forEach(g,this); +return this;}:function(e){var l=F(this.className);F(e).forEach(l.erase,l);this.className=l.join(" ");return this;},toggleClass:function(e,l){if(l==null){l=!this.hasClass(e); +}return(l)?this.addClass(e):this.removeClass(e);},adopt:function(){var L=this,e,N=Array.flatten(arguments),M=N.length;if(M>1){L=e=document.createDocumentFragment(); +}for(var K=0;K<M;K++){var l=document.id(N[K],true);if(l){L.appendChild(l);}}if(e){this.appendChild(e);}return this;},appendText:function(l,e){return this.grab(this.getDocument().newTextNode(l),e); +},grab:function(l,e){A[e||"bottom"](document.id(l,true),this);return this;},inject:function(l,e){A[e||"bottom"](this,document.id(l,true));return this;},replaces:function(e){e=document.id(e,true); +e.parentNode.replaceChild(this,e);return this;},wraps:function(l,e){l=document.id(l,true);return this.replaces(l).grab(l,e);},getSelected:function(){this.selectedIndex; +return new Elements(Array.from(this.options).filter(function(e){return e.selected;}));},toQueryString:function(){var e=[];this.getElements("input, select, textarea").each(function(K){var l=K.type; +if(!K.name||K.disabled||l=="submit"||l=="reset"||l=="file"||l=="image"){return;}var L=(K.get("tag")=="select")?K.getSelected().map(function(M){return document.id(M).get("value"); +}):((l=="radio"||l=="checkbox")&&!K.checked)?null:K.get("value");Array.from(L).each(function(M){if(typeof M!="undefined"){e.push(encodeURIComponent(K.name)+"="+encodeURIComponent(M)); +}});});return e.join("&");}});var I={before:"beforeBegin",after:"afterEnd",bottom:"beforeEnd",top:"afterBegin",inside:"beforeEnd"};Element.implement("appendHTML",("insertAdjacentHTML" in document.createElement("div"))?function(l,e){this.insertAdjacentHTML(I[e||"bottom"],l); +return this;}:function(P,M){var K=new Element("div",{html:P}),O=K.childNodes,L=K.firstChild;if(!L){return this;}if(O.length>1){L=document.createDocumentFragment(); +for(var N=0,e=O.length;N<e;N++){L.appendChild(O[N]);}}A[M||"bottom"](L,this);return this;});var m={},D={};var G=function(e){return(D[e]||(D[e]={}));};var z=function(l){var e=l.uniqueNumber; +if(l.removeEvents){l.removeEvents();}if(l.clearAttributes){l.clearAttributes();}if(e!=null){delete m[e];delete D[e];}return l;};var H={input:"checked",option:"selected",textarea:"value"}; +Element.implement({destroy:function(){var e=z(this).getElementsByTagName("*");Array.each(e,z);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose); +return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},clone:function(N,L){N=N!==false;var S=this.cloneNode(N),K=[S],M=[this],Q; +if(N){K.append(Array.from(S.getElementsByTagName("*")));M.append(Array.from(this.getElementsByTagName("*")));}for(Q=K.length;Q--;){var O=K[Q],R=M[Q];if(!L){O.removeAttribute("id"); +}if(O.clearAttributes){O.clearAttributes();O.mergeAttributes(R);O.removeAttribute("uniqueNumber");if(O.options){var V=O.options,e=R.options;for(var P=V.length; +P--;){V[P].selected=e[P].selected;}}}var l=H[R.tagName.toLowerCase()];if(l&&R[l]){O[l]=R[l];}}if(i){var T=S.getElementsByTagName("object"),U=this.getElementsByTagName("object"); +for(Q=T.length;Q--;){T[Q].outerHTML=U[Q].outerHTML;}}return document.id(S);}});[Element,Window,Document].invoke("implement",{addListener:function(l,e){if(window.attachEvent&&!window.addEventListener){m[Slick.uidOf(this)]=this; +}if(this.addEventListener){this.addEventListener(l,e,!!arguments[2]);}else{this.attachEvent("on"+l,e);}return this;},removeListener:function(l,e){if(this.removeEventListener){this.removeEventListener(l,e,!!arguments[2]); +}else{this.detachEvent("on"+l,e);}return this;},retrieve:function(l,e){var L=G(Slick.uidOf(this)),K=L[l];if(e!=null&&K==null){K=L[l]=e;}return K!=null?K:null; +},store:function(l,e){var K=G(Slick.uidOf(this));K[l]=e;return this;},eliminate:function(e){var l=G(Slick.uidOf(this));delete l[e];return this;}});if(window.attachEvent&&!window.addEventListener){var J=function(){Object.each(m,z); +if(window.CollectGarbage){CollectGarbage();}window.removeListener("unload",J);};window.addListener("unload",J);}Element.Properties={};Element.Properties.style={set:function(e){this.style.cssText=e; +},get:function(){return this.style.cssText;},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase(); +}};Element.Properties.html={set:function(e){if(e==null){e="";}else{if(typeOf(e)=="array"){e=e.join("");}}this.innerHTML=e;},erase:function(){this.innerHTML=""; +}};var a=true,h=true,C=true;var x=document.createElement("div");x.innerHTML="<nav></nav>";a=(x.childNodes.length==1);if(!a){var w="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),b=document.createDocumentFragment(),y=w.length; +while(y--){b.createElement(w[y]);}}x=null;h=Function.attempt(function(){var e=document.createElement("table");e.innerHTML="<tr><td></td></tr>";return true; +});var c=document.createElement("tr"),r="<td></td>";c.innerHTML=r;C=(c.innerHTML==r);c=null;if(!h||!C||!a){Element.Properties.html.set=(function(l){var e={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]}; +e.thead=e.tfoot=e.tbody;return function(K){var L=e[this.get("tag")];if(!L&&!a){L=[0,"",""];}if(!L){return l.call(this,K);}var O=L[0],N=document.createElement("div"),M=N; +if(!a){b.appendChild(N);}N.innerHTML=[L[1],K,L[2]].flatten().join("");while(O--){M=M.firstChild;}this.empty().adopt(M.childNodes);if(!a){b.removeChild(N); +}N=null;};})(Element.Properties.html.set);}var q=document.createElement("form");q.innerHTML="<select><option>s</option></select>";if(q.firstChild.value!="s"){Element.Properties.value={set:function(N){var l=this.get("tag"); +if(l!="select"){return this.setProperty("value",N);}var K=this.getElements("option");N=String(N);for(var L=0;L<K.length;L++){var M=K[L],e=M.getAttributeNode("value"),O=(e&&e.specified)?M.value:M.get("text"); +if(O===N){return M.selected=true;}}},get:function(){var K=this,l=K.get("tag");if(l!="select"&&l!="option"){return this.getProperty("value");}if(l=="select"&&!(K=K.getSelected()[0])){return""; +}var e=K.getAttributeNode("value");return(e&&e.specified)?K.value:K.get("text");}};}q=null;if(document.createElement("div").getAttributeNode("id")){Element.Properties.id={set:function(e){this.id=this.getAttributeNode("id").value=e; +},get:function(){return this.id||null;},erase:function(){this.id=this.getAttributeNode("id").value="";}};}})();(function(){var l=document.html,f;f=document.createElement("div"); +f.style.color="red";f.style.color=null;var e=f.style.color=="red";var k="1px solid #123abc";f.style.border=k;var o=f.style.border!=k;f=null;var n=!!window.getComputedStyle; +Element.Properties.styles={set:function(r){this.setStyles(r);}};var j=(l.style.opacity!=null),g=(l.style.filter!=null),q=/alpha\(opacity=([\d.]+)\)/i;var b=function(s,r){s.store("$opacity",r); +s.style.visibility=r>0||r==null?"visible":"hidden";};var p=function(r,v,u){var t=r.style,s=t.filter||r.getComputedStyle("filter")||"";t.filter=(v.test(s)?s.replace(v,u):s+" "+u).trim(); +if(!t.filter){t.removeAttribute("filter");}};var h=(j?function(s,r){s.style.opacity=r;}:(g?function(s,r){if(!s.currentStyle||!s.currentStyle.hasLayout){s.style.zoom=1; +}if(r==null||r==1){p(s,q,"");if(r==1&&i(s)!=1){p(s,q,"alpha(opacity=100)");}}else{p(s,q,"alpha(opacity="+(r*100).limit(0,100).round()+")");}}:b));var i=(j?function(s){var r=s.style.opacity||s.getComputedStyle("opacity"); +return(r=="")?1:r.toFloat();}:(g?function(s){var t=(s.style.filter||s.getComputedStyle("filter")),r;if(t){r=t.match(q);}return(r==null||t==null)?1:(r[1]/100); +}:function(s){var r=s.retrieve("$opacity");if(r==null){r=(s.style.visibility=="hidden"?0:1);}return r;}));var d=(l.style.cssFloat==null)?"styleFloat":"cssFloat",a={left:"0%",top:"0%",center:"50%",right:"100%",bottom:"100%"},c=(l.style.backgroundPositionX!=null); +var m=function(r,s){if(s=="backgroundPosition"){r.removeAttribute(s+"X");s+="Y";}r.removeAttribute(s);};Element.implement({getComputedStyle:function(t){if(!n&&this.currentStyle){return this.currentStyle[t.camelCase()]; +}var s=Element.getDocument(this).defaultView,r=s?s.getComputedStyle(this,null):null;return(r)?r.getPropertyValue((t==d)?"float":t.hyphenate()):"";},setStyle:function(s,r){if(s=="opacity"){if(r!=null){r=parseFloat(r); +}h(this,r);return this;}s=(s=="float"?d:s).camelCase();if(typeOf(r)!="string"){var t=(Element.Styles[s]||"@").split(" ");r=Array.from(r).map(function(v,u){if(!t[u]){return""; +}return(typeOf(v)=="number")?t[u].replace("@",Math.round(v)):v;}).join(" ");}else{if(r==String(Number(r))){r=Math.round(r);}}this.style[s]=r;if((r==""||r==null)&&e&&this.style.removeAttribute){m(this.style,s); +}return this;},getStyle:function(x){if(x=="opacity"){return i(this);}x=(x=="float"?d:x).camelCase();var r=this.style[x];if(!r||x=="zIndex"){if(Element.ShortStyles.hasOwnProperty(x)){r=[]; +for(var w in Element.ShortStyles[x]){r.push(this.getStyle(w));}return r.join(" ");}r=this.getComputedStyle(x);}if(c&&/^backgroundPosition[XY]?$/.test(x)){return r.replace(/(top|right|bottom|left)/g,function(s){return a[s]; +})||"0px";}if(!r&&x=="backgroundPosition"){return"0px 0px";}if(r){r=String(r);var u=r.match(/rgba?\([\d\s,]+\)/);if(u){r=r.replace(u[0],u[0].rgbToHex()); +}}if(!n&&!this.style[x]){if((/^(height|width)$/).test(x)&&!(/px$/.test(r))){var t=(x=="width")?["left","right"]:["top","bottom"],v=0;t.each(function(s){v+=this.getStyle("border-"+s+"-width").toInt()+this.getStyle("padding-"+s).toInt(); +},this);return this["offset"+x.capitalize()]-v+"px";}if((/^border(.+)Width|margin|padding/).test(x)&&isNaN(parseFloat(r))){return"0px";}}if(o&&/^border(Top|Right|Bottom|Left)?$/.test(x)&&/^#/.test(r)){return r.replace(/^(.+)\s(.+)\s(.+)$/,"$2 $3 $1"); +}return r;},setStyles:function(s){for(var r in s){this.setStyle(r,s[r]);}return this;},getStyles:function(){var r={};Array.flatten(arguments).each(function(s){r[s]=this.getStyle(s); +},this);return r;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundSize:"@px",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"}; +Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(x){var w=Element.ShortStyles; +var s=Element.Styles;["margin","padding"].each(function(y){var z=y+x;w[y][z]=s[z]="@px";});var v="border"+x;w.border[v]=s[v]="@px @ rgb(@, @, @)";var u=v+"Width",r=v+"Style",t=v+"Color"; +w[v]={};w.borderWidth[u]=w[v][u]=s[u]="@px";w.borderStyle[r]=w[v][r]=s[r]="@";w.borderColor[t]=w[v][t]=s[t]="rgb(@, @, @)";});if(c){Element.ShortStyles.backgroundPosition={backgroundPositionX:"@",backgroundPositionY:"@"}; +}})();(function(){Element.Properties.events={set:function(b){this.addEvents(b);}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{}); +if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this;}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f); +}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k);}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j); +};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow());if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]); +}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events");if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d); +if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e];if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e); +}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this; +},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);}return this;}var c=this.retrieve("events");if(!c){return this; +}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);},this);delete c[b]; +}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c); }else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b); -}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1}; -var a=function(b){var c=b.relatedTarget;if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c)); -};Element.Events={mouseenter:{base:"mouseover",condition:a},mouseleave:{base:"mouseout",condition:a},mousewheel:{base:(Browser.firefox)?"DOMMouseScroll":"mousewheel"}}; -if(!window.addEventListener){Element.NativeEvents.propertychange=2;Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change"; -},condition:function(b){return !!(this.type!="radio"||this.checked);}};}})();(function(){var c=!!window.addEventListener;Element.NativeEvents.focusin=Element.NativeEvents.focusout=2; -var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p);}p=document.id(p.parentNode);}};var a={mouseenter:{base:"mouseover"},mouseleave:{base:"mouseout"},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}}; +}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,hashchange:1,popstate:2,error:1,abort:1,scroll:1}; +Element.Events={mousewheel:{base:"onwheel" in document?"wheel":"onmousewheel" in document?"mousewheel":"DOMMouseScroll"}};var a=function(b){var c=b.relatedTarget; +if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c));};if("onmouseenter" in document.documentElement){Element.NativeEvents.mouseenter=Element.NativeEvents.mouseleave=2; +Element.MouseenterCheck=a;}else{Element.Events.mouseenter={base:"mouseover",condition:a};Element.Events.mouseleave={base:"mouseout",condition:a};}if(!window.addEventListener){Element.NativeEvents.propertychange=2; +Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change";},condition:function(b){return b.type!="propertychange"||b.event.propertyName=="checked"; +}};}})();(function(){var c=!!window.addEventListener;Element.NativeEvents.focusin=Element.NativeEvents.focusout=2;var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p); +}p=document.id(p.parentNode);}};var a={mouseenter:{base:"mouseover",condition:Element.MouseenterCheck},mouseleave:{base:"mouseout",condition:Element.MouseenterCheck},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}}; var b="$delegation:";var i=function(l){return{base:"focusin",remove:function(m,o){var p=m.retrieve(b+l+"listeners",{})[o];if(p&&p.forms){for(var n=p.forms.length; n--;){p.forms[n].removeEvent(l,p.fns[n]);}}},listen:function(x,r,v,n,t,s){var o=(t.get("tag")=="form")?t:n.target.getParent("form");if(!o){return;}var u=x.retrieve(b+l+"listeners",{}),p=u[s]||{forms:[],fns:[]},m=p.forms,w=p.fns; if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEvent(l,q);w.push(q);u[s]=p;x.store(b+l+"listeners",u);}};};var d=function(l){return{base:"focusin",listen:function(m,n,p,q,r){var o={blur:function(){this.removeEvents(o); @@ -340,24 +361,24 @@ if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEve }var h=Element.prototype,f=h.addEvent,j=h.removeEvent;var e=function(l,m){return function(r,q,n){if(r.indexOf(":relay")==-1){return l.call(this,r,q,n); }var o=Slick.parse(r).expressions[0][0];if(o.pseudos[0].key!="relay"){return l.call(this,r,q,n);}var p=o.tag;o.pseudos.slice(1).each(function(s){p+=":"+s.key+(s.value?"("+s.value+")":""); });l.call(this,r,q);return m.call(this,p,o.pseudos[0].value,q);};};var g={addEvent:function(v,q,x){var t=this.retrieve("$delegates",{}),r=t[v];if(r){for(var y in r){if(r[y].fn==x&&r[y].match==q){return this; -}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(w&&w.condition){var l=q,m=w.condition;q=function(C,B){return l(C,B)&&m.call(C,B,v); -};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s);}}:function(B,C){if(!C&&B&&B.target){C=B.target; -}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture);},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r]; -if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u);}delete p[u];q[m]=p;return j.call(this,r,w);}var o,v; -if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o);}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o); -}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)});})();(function(){var h=document.createElement("div"),e=document.createElement("div"); -h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null;var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName); -};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n);}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize(); -}return{x:this.offsetWidth,y:this.offsetHeight};},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight}; -},getScroll:function(){if(a(this)){return this.getWindow().getScroll();}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0}; -while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop;n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null; -}var n=(k(m,"position")=="static")?i:l;while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null; -}try{return m.offsetParent;}catch(n){}return null;},getOffsets:function(){if(this.getBoundingClientRect&&!Browser.Platform.ios){var r=this.getBoundingClientRect(),o=document.id(this.getDocument().documentElement),q=o.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed"); -return{x:r.left.toInt()+t.x+((s)?0:q.x)-o.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-o.clientTop};}var n=this,m={x:0,y:0};if(a(this)){return m;}while(n&&!a(n)){m.x+=n.offsetLeft; -m.y+=n.offsetTop;if(Browser.firefox){if(!c(n)){m.x+=b(n);m.y+=g(n);}var p=n.parentNode;if(p&&k(p,"overflow")!="visible"){m.x+=b(p);m.y+=g(p);}}else{if(n!=this&&Browser.safari){m.x+=b(n); -m.y+=g(n);}}n=n.offsetParent;}if(Browser.firefox&&!c(this)){m.x-=b(this);m.y-=g(this);}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls(); -var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition();return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates(); -}var m=this.getPosition(o),n=this.getSize();var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")}; +}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(n.condition||w&&w.condition){var l=q,m=n.condition||w.condition; +q=function(C,B){return l(C,B)&&m.call(C,B,v);};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s); +}}:function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture); +},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r];if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u); +}delete p[u];q[m]=p;return j.call(this,r,w,l.capture);}var o,v;if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o); +}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o);}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)}); +})();(function(){var h=document.createElement("div"),e=document.createElement("div");h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null; +var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName);};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n); +}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize();}return{x:this.offsetWidth,y:this.offsetHeight}; +},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};},getScroll:function(){if(a(this)){return this.getWindow().getScroll(); +}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0};while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop; +n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}var n=(k(m,"position")=="static")?i:l; +while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}try{return m.offsetParent; +}catch(n){}return null;},getOffsets:function(){var n=this.getBoundingClientRect;if(n){var r=this.getBoundingClientRect(),p=document.id(this.getDocument().documentElement),q=p.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed"); +return{x:r.left.toInt()+t.x+((s)?0:q.x)-p.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-p.clientTop};}var o=this,m={x:0,y:0};if(a(this)){return m;}while(o&&!a(o)){m.x+=o.offsetLeft; +m.y+=o.offsetTop;o=o.offsetParent;}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls();var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition(); +return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates();}var m=this.getPosition(o),n=this.getSize(); +var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")}; },setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight}; },getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body; return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize(); @@ -377,29 +398,32 @@ this.frames=i||Math.round(this.duration/this.frameInterval);this.fireEvent("star d.call(this,this.options.fps);if(this.frames==this.frame){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject); }}else{this.fireEvent("stop",this.subject);}}return this;},cancel:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);this.frame=this.frames; this.fireEvent("cancel",this.subject).clearChain();}return this;},pause:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);}return this; -},resume:function(){if((this.frame<this.frames)&&!this.isRunning()){b.call(this,this.options.fps);}return this;},isRunning:function(){var g=e[this.options.fps]; -return g&&g.contains(this);}});f.compute=function(i,h,g){return(h-i)*g+i;};f.Durations={"short":250,normal:500,"long":1000};var e={},c={};var a=function(){var h=Date.now(); -for(var j=this.length;j--;){var g=this[j];if(g){g.step(h);}}};var b=function(h){var g=e[h]||(e[h]=[]);g.push(this);if(!c[h]){c[h]=a.periodical(Math.round(1000/h),g); -}};var d=function(h){var g=e[h];if(g){g.erase(this);if(!g.length&&c[h]){delete e[h];c[h]=clearInterval(c[h]);}}};})();Fx.CSS=new Class({Extends:Fx,prepare:function(c,d,b){b=Array.from(b); -if(b[1]==null){b[1]=b[0];b[0]=c.getStyle(d);}var a=b.map(this.parse);return{from:a[0],to:a[1]};},parse:function(a){a=Function.from(a)();a=(typeof a=="string")?a.split(" "):Array.from(a); -return a.map(function(c){c=String(c);var b=false;Object.each(Fx.CSS.Parsers,function(f,e){if(b){return;}var d=f.parse(c);if(d||d===0){b={value:d,parser:f}; -}});b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser}); +},resume:function(){if(this.isPaused()){b.call(this,this.options.fps);}return this;},isRunning:function(){var g=e[this.options.fps];return g&&g.contains(this); +},isPaused:function(){return(this.frame<this.frames)&&!this.isRunning();}});f.compute=function(i,h,g){return(h-i)*g+i;};f.Durations={"short":250,normal:500,"long":1000}; +var e={},c={};var a=function(){var h=Date.now();for(var j=this.length;j--;){var g=this[j];if(g){g.step(h);}}};var b=function(h){var g=e[h]||(e[h]=[]);g.push(this); +if(!c[h]){c[h]=a.periodical(Math.round(1000/h),g);}};var d=function(h){var g=e[h];if(g){g.erase(this);if(!g.length&&c[h]){delete e[h];c[h]=clearInterval(c[h]); +}}};})();Fx.CSS=new Class({Extends:Fx,prepare:function(b,e,a){a=Array.from(a);var h=a[0],g=a[1];if(g==null){g=h;h=b.getStyle(e);var c=this.options.unit; +if(c&&h&&typeof h=="string"&&h.slice(-c.length)!=c&&parseFloat(h)!=0){b.setStyle(e,g+c);var d=b.getComputedStyle(e);if(!(/px$/.test(d))){d=b.style[("pixel-"+e).camelCase()]; +if(d==null){var f=b.style.left;b.style.left=g+c;d=b.style.pixelLeft;b.style.left=f;}}h=(g||1)/(parseFloat(d)||1)*(parseFloat(h)||0);b.setStyle(e,h+c);}}return{from:this.parse(h),to:this.parse(g)}; +},parse:function(a){a=Function.from(a)();a=(typeof a=="string")?a.split(" "):Array.from(a);return a.map(function(c){c=String(c);var b=false;Object.each(Fx.CSS.Parsers,function(f,e){if(b){return; +}var d=f.parse(c);if(d||d===0){b={value:d,parser:f};}});b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser}); });a.$family=Function.from("fx:css:value");return a;},serve:function(c,b){if(typeOf(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b)); -});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var c={},b=new RegExp("^"+a.escapeRegExp()+"$"); -Array.each(document.styleSheets,function(f,e){var d=f.href;if(d&&d.contains("://")&&!d.contains(document.domain)){return;}var g=f.rules||f.cssRules;Array.each(g,function(k,h){if(!k.style){return; -}var j=(k.selectorText)?k.selectorText.replace(/^\w+/,function(i){return i.toLowerCase();}):null;if(!j||!b.test(j)){return;}Object.each(Element.Styles,function(l,i){if(!k.style[i]||Element.ShortStyles[i]){return; -}l=String(k.style[i]);c[i]=((/^rgb/).test(l))?l.rgbToHex():l;});});});return Fx.CSS.Cache[a]=c;}});Fx.CSS.Cache={};Fx.CSS.Parsers={Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true); +});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var d={},c=new RegExp("^"+a.escapeRegExp()+"$"); +var b=function(e){Array.each(e,function(h,f){if(h.media){b(h.rules||h.cssRules);return;}if(!h.style){return;}var g=(h.selectorText)?h.selectorText.replace(/^\w+/,function(i){return i.toLowerCase(); +}):null;if(!g||!c.test(g)){return;}Object.each(Element.Styles,function(j,i){if(!h.style[i]||Element.ShortStyles[i]){return;}j=String(h.style[i]);d[i]=((/^rgb/).test(j))?j.rgbToHex():j; +});});};Array.each(document.styleSheets,function(g,f){var e=g.href;if(e&&e.indexOf("://")>-1&&e.indexOf(document.domain)==-1){return;}var h=g.rules||g.cssRules; +b(h);});return Fx.CSS.Cache[a]=d;}});Fx.CSS.Cache={};Fx.CSS.Parsers={Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true); }return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a)); });},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:Function.from(false),compute:function(b,a){return a; },serve:function(a){return a;}}};Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);},set:function(b,a){if(arguments.length==1){a=b; b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this; }var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);return this.parent(a.from,a.to); }});Element.Properties.tween={set:function(a){this.get("tween").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("tween");if(!a){a=new Fx.Tween(this,{link:"cancel"}); -this.store("tween",a);}return a;}};Element.implement({tween:function(a,c,b){this.get("tween").start(a,c,b);return this;},fade:function(c){var d=this.get("tween"),f,e,a; -if(c==null){c="toggle";}switch(c){case"in":f="start";e=1;break;case"out":f="start";e=0;break;case"show":f="set";e=1;break;case"hide":f="set";e=0;break; -case"toggle":var b=this.retrieve("fade:flag",this.getStyle("opacity")==1);f="start";e=b?0:1;this.store("fade:flag",!b);a=true;break;default:f="start";e=c; -}if(!a){this.eliminate("fade:flag");}d[f]("opacity",e);if(f=="set"||e!=0){this.setStyle("visibility",e==0?"hidden":"visible");}else{d.chain(function(){this.element.setStyle("visibility","hidden"); -});}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));a=(a=="transparent")?"#fff":a; +this.store("tween",a);}return a;}};Element.implement({tween:function(a,c,b){this.get("tween").start(a,c,b);return this;},fade:function(d){var e=this.get("tween"),g,c=["opacity"].append(arguments),a; +if(c[1]==null){c[1]="toggle";}switch(c[1]){case"in":g="start";c[1]=1;break;case"out":g="start";c[1]=0;break;case"show":g="set";c[1]=1;break;case"hide":g="set"; +c[1]=0;break;case"toggle":var b=this.retrieve("fade:flag",this.getStyle("opacity")==1);g="start";c[1]=b?0:1;this.store("fade:flag",!b);a=true;break;default:g="start"; +}if(!a){this.eliminate("fade:flag");}e[g].apply(e,c);var f=c[c.length-1];if(g=="set"||f!=0){this.setStyle("visibility",f==0?"hidden":"visible");}else{e.chain(function(){this.element.setStyle("visibility","hidden"); +this.callChain();});}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));a=(a=="transparent")?"#fff":a; }var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original")); b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a); },set:function(a){if(typeof a=="string"){a=this.search(a);}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={}; @@ -427,12 +451,12 @@ return this;},getHeader:function(e){return Function.attempt(function(){return th o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString(); break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e; j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g; -}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.contains("?")?"&":"?")+String.uniqueID(); -}if(j&&e=="get"){f+=(f.contains("?")?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this); +}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.indexOf("?")>-1?"&":"?")+String.uniqueID(); +}if(j&&(e=="get"||e=="delete")){f+=(f.indexOf("?")>-1?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this); }n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true; }n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]); -}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this); -}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d; +}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}else{if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this); +}}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d; if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e}; if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e); return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")}); @@ -449,9 +473,9 @@ c.tree=b.childNodes;c.elements=b.getElements(e.filter||"*");if(e.filter){c.tree= return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON(); }switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[]; Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj; -case"null":return"null";}return null;};JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure||JSON.secure){if(JSON.parse){return JSON.parse(string); -}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure.");}}return eval("("+string+")"); -};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"}); +case"null":return"null";}return null;};JSON.secure=true;JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure==null){secure=JSON.secure; +}if(secure){if(JSON.parse){return JSON.parse(string);}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure."); +}}return eval("("+string+")");};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"}); },success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure(); }else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b; this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path; @@ -464,13 +488,4 @@ k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.l if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h); c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a); }else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this); -}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);(function(){var Swiff=this.Swiff=new Class({Implements:Options,options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"window",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object; -},initialize:function(path,options){this.instance="Swiff_"+String.uniqueID();this.setOptions(options);options=this.options;var id=this.id=options.id||this.instance; -var container=document.id(options.container);Swiff.CallBacks[this.instance]={};var params=options.params,vars=options.vars,callBacks=options.callBacks; -var properties=Object.append({height:options.height,width:options.width},options.properties);var self=this;for(var callBack in callBacks){Swiff.CallBacks[this.instance][callBack]=(function(option){return function(){return option.apply(self.object,arguments); -};})(callBacks[callBack]);vars[callBack]="Swiff.CallBacks."+this.instance+"."+callBack;}params.flashVars=Object.toQueryString(vars);if(Browser.ie){properties.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"; -params.movie=path;}else{properties.type="application/x-shockwave-flash";}properties.data=path;var build='<object id="'+id+'"';for(var property in properties){build+=" "+property+'="'+properties[property]+'"'; -}build+=">";for(var param in params){if(params[param]){build+='<param name="'+param+'" value="'+params[param]+'" />';}}build+="</object>";this.object=((container)?container.empty():new Element("div")).set("html",build).firstChild; -},replaces:function(element){element=document.id(element,true);element.parentNode.replaceChild(this.toElement(),element);return this;},inject:function(element){document.id(element,true).appendChild(this.toElement()); -return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].append(arguments));}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>"); -return eval(rs);};})();
\ No newline at end of file +}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);
\ No newline at end of file diff --git a/module/webui/themes/dark/js/static/mootools-more.js b/module/webui/themes/dark/js/static/mootools-more.js new file mode 100644 index 000000000..c7f4a1a0e --- /dev/null +++ b/module/webui/themes/dark/js/static/mootools-more.js @@ -0,0 +1,2856 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/more/c1cc18c2fff04bcc58921b4dff80a6f1 + +packager build: + - packager build More/Form.Request More/Fx.Reveal More/Sortables More/Request.Periodical More/Color + +... +*/ + +/* +--- + +script: More.js + +name: More + +description: MooTools More + +license: MIT-style license + +authors: + - Guillermo Rauch + - Thomas Aylott + - Scott Kyle + - Arian Stolwijk + - Tim Wienk + - Christoph Pojer + - Aaron Newton + - Jacob Thornton + +requires: + - Core/MooTools + +provides: [MooTools.More] + +... +*/ + +MooTools.More = { + version: '1.5.0', + build: '73db5e24e6e9c5c87b3a27aebef2248053f7db37' +}; + + +/* +--- + +script: Class.Binds.js + +name: Class.Binds + +description: Automagically binds specified methods in a class to the instance of the class. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - MooTools.More + +provides: [Class.Binds] + +... +*/ + +Class.Mutators.Binds = function(binds){ + if (!this.prototype.initialize) this.implement('initialize', function(){}); + return Array.from(binds).concat(this.prototype.Binds || []); +}; + +Class.Mutators.initialize = function(initialize){ + return function(){ + Array.from(this.Binds).each(function(name){ + var original = this[name]; + if (original) this[name] = original.bind(this); + }, this); + return initialize.apply(this, arguments); + }; +}; + + +/* +--- + +script: Class.Occlude.js + +name: Class.Occlude + +description: Prevents a class from being applied to a DOM element twice. + +license: MIT-style license. + +authors: + - Aaron Newton + +requires: + - Core/Class + - Core/Element + - MooTools.More + +provides: [Class.Occlude] + +... +*/ + +Class.Occlude = new Class({ + + occlude: function(property, element){ + element = document.id(element || this.element); + var instance = element.retrieve(property || this.property); + if (instance && !this.occluded) + return (this.occluded = instance); + + this.occluded = false; + element.store(property || this.property, this); + return this.occluded; + } + +}); + + +/* +--- + +script: Class.Refactor.js + +name: Class.Refactor + +description: Extends a class onto itself with new property, preserving any items attached to the class's namespace. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - MooTools.More + +# Some modules declare themselves dependent on Class.Refactor +provides: [Class.refactor, Class.Refactor] + +... +*/ + +Class.refactor = function(original, refactors){ + + Object.each(refactors, function(item, name){ + var origin = original.prototype[name]; + origin = (origin && origin.$origin) || origin || function(){}; + original.implement(name, (typeof item == 'function') ? function(){ + var old = this.previous; + this.previous = origin; + var value = item.apply(this, arguments); + this.previous = old; + return value; + } : item); + }); + + return original; + +}; + + +/* +--- + +script: Element.Measure.js + +name: Element.Measure + +description: Extends the Element native object to include methods useful in measuring dimensions. + +credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz" + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - Core/Element.Dimensions + - MooTools.More + +provides: [Element.Measure] + +... +*/ + +(function(){ + +var getStylesList = function(styles, planes){ + var list = []; + Object.each(planes, function(directions){ + Object.each(directions, function(edge){ + styles.each(function(style){ + list.push(style + '-' + edge + (style == 'border' ? '-width' : '')); + }); + }); + }); + return list; +}; + +var calculateEdgeSize = function(edge, styles){ + var total = 0; + Object.each(styles, function(value, style){ + if (style.test(edge)) total = total + value.toInt(); + }); + return total; +}; + +var isVisible = function(el){ + return !!(!el || el.offsetHeight || el.offsetWidth); +}; + + +Element.implement({ + + measure: function(fn){ + if (isVisible(this)) return fn.call(this); + var parent = this.getParent(), + toMeasure = []; + while (!isVisible(parent) && parent != document.body){ + toMeasure.push(parent.expose()); + parent = parent.getParent(); + } + var restore = this.expose(), + result = fn.call(this); + restore(); + toMeasure.each(function(restore){ + restore(); + }); + return result; + }, + + expose: function(){ + if (this.getStyle('display') != 'none') return function(){}; + var before = this.style.cssText; + this.setStyles({ + display: 'block', + position: 'absolute', + visibility: 'hidden' + }); + return function(){ + this.style.cssText = before; + }.bind(this); + }, + + getDimensions: function(options){ + options = Object.merge({computeSize: false}, options); + var dim = {x: 0, y: 0}; + + var getSize = function(el, options){ + return (options.computeSize) ? el.getComputedSize(options) : el.getSize(); + }; + + var parent = this.getParent('body'); + + if (parent && this.getStyle('display') == 'none'){ + dim = this.measure(function(){ + return getSize(this, options); + }); + } else if (parent){ + try { //safari sometimes crashes here, so catch it + dim = getSize(this, options); + }catch(e){} + } + + return Object.append(dim, (dim.x || dim.x === 0) ? { + width: dim.x, + height: dim.y + } : { + x: dim.width, + y: dim.height + } + ); + }, + + getComputedSize: function(options){ + + + options = Object.merge({ + styles: ['padding','border'], + planes: { + height: ['top','bottom'], + width: ['left','right'] + }, + mode: 'both' + }, options); + + var styles = {}, + size = {width: 0, height: 0}, + dimensions; + + if (options.mode == 'vertical'){ + delete size.width; + delete options.planes.width; + } else if (options.mode == 'horizontal'){ + delete size.height; + delete options.planes.height; + } + + getStylesList(options.styles, options.planes).each(function(style){ + styles[style] = this.getStyle(style).toInt(); + }, this); + + Object.each(options.planes, function(edges, plane){ + + var capitalized = plane.capitalize(), + style = this.getStyle(plane); + + if (style == 'auto' && !dimensions) dimensions = this.getDimensions(); + + style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt(); + size['total' + capitalized] = style; + + edges.each(function(edge){ + var edgesize = calculateEdgeSize(edge, styles); + size['computed' + edge.capitalize()] = edgesize; + size['total' + capitalized] += edgesize; + }); + + }, this); + + return Object.append(size, styles); + } + +}); + +})(); + + +/* +--- + +script: Element.Position.js + +name: Element.Position + +description: Extends the Element native object to include methods useful positioning elements relative to others. + +license: MIT-style license + +authors: + - Aaron Newton + - Jacob Thornton + +requires: + - Core/Options + - Core/Element.Dimensions + - Element.Measure + +provides: [Element.Position] + +... +*/ + +(function(original){ + +var local = Element.Position = { + + options: {/* + edge: false, + returnPos: false, + minimum: {x: 0, y: 0}, + maximum: {x: 0, y: 0}, + relFixedPosition: false, + ignoreMargins: false, + ignoreScroll: false, + allowNegative: false,*/ + relativeTo: document.body, + position: { + x: 'center', //left, center, right + y: 'center' //top, center, bottom + }, + offset: {x: 0, y: 0} + }, + + getOptions: function(element, options){ + options = Object.merge({}, local.options, options); + local.setPositionOption(options); + local.setEdgeOption(options); + local.setOffsetOption(element, options); + local.setDimensionsOption(element, options); + return options; + }, + + setPositionOption: function(options){ + options.position = local.getCoordinateFromValue(options.position); + }, + + setEdgeOption: function(options){ + var edgeOption = local.getCoordinateFromValue(options.edge); + options.edge = edgeOption ? edgeOption : + (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} : + {x: 'left', y: 'top'}; + }, + + setOffsetOption: function(element, options){ + var parentOffset = {x: 0, y: 0}; + var parentScroll = {x: 0, y: 0}; + var offsetParent = element.measure(function(){ + return document.id(this.getOffsetParent()); + }); + + if (!offsetParent || offsetParent == element.getDocument().body) return; + + parentScroll = offsetParent.getScroll(); + parentOffset = offsetParent.measure(function(){ + var position = this.getPosition(); + if (this.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.x += scroll.x; + position.y += scroll.y; + } + return position; + }); + + options.offset = { + parentPositioned: offsetParent != document.id(options.relativeTo), + x: options.offset.x - parentOffset.x + parentScroll.x, + y: options.offset.y - parentOffset.y + parentScroll.y + }; + }, + + setDimensionsOption: function(element, options){ + options.dimensions = element.getDimensions({ + computeSize: true, + styles: ['padding', 'border', 'margin'] + }); + }, + + getPosition: function(element, options){ + var position = {}; + options = local.getOptions(element, options); + var relativeTo = document.id(options.relativeTo) || document.body; + + local.setPositionCoordinates(options, position, relativeTo); + if (options.edge) local.toEdge(position, options); + + var offset = options.offset; + position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt(); + position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt(); + + local.toMinMax(position, options); + + if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position); + if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position); + if (options.ignoreMargins) local.toIgnoreMargins(position, options); + + position.left = Math.ceil(position.left); + position.top = Math.ceil(position.top); + delete position.x; + delete position.y; + + return position; + }, + + setPositionCoordinates: function(options, position, relativeTo){ + var offsetY = options.offset.y, + offsetX = options.offset.x, + calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(), + top = calc.y, + left = calc.x, + winSize = window.getSize(); + + switch(options.position.x){ + case 'left': position.x = left + offsetX; break; + case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break; + default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break; + } + + switch(options.position.y){ + case 'top': position.y = top + offsetY; break; + case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break; + default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break; + } + }, + + toMinMax: function(position, options){ + var xy = {left: 'x', top: 'y'}, value; + ['minimum', 'maximum'].each(function(minmax){ + ['left', 'top'].each(function(lr){ + value = options[minmax] ? options[minmax][xy[lr]] : null; + if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value; + }); + }); + }, + + toRelFixedPosition: function(relativeTo, position){ + var winScroll = window.getScroll(); + position.top += winScroll.y; + position.left += winScroll.x; + }, + + toIgnoreScroll: function(relativeTo, position){ + var relScroll = relativeTo.getScroll(); + position.top -= relScroll.y; + position.left -= relScroll.x; + }, + + toIgnoreMargins: function(position, options){ + position.left += options.edge.x == 'right' + ? options.dimensions['margin-right'] + : (options.edge.x != 'center' + ? -options.dimensions['margin-left'] + : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2)); + + position.top += options.edge.y == 'bottom' + ? options.dimensions['margin-bottom'] + : (options.edge.y != 'center' + ? -options.dimensions['margin-top'] + : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2)); + }, + + toEdge: function(position, options){ + var edgeOffset = {}, + dimensions = options.dimensions, + edge = options.edge; + + switch(edge.x){ + case 'left': edgeOffset.x = 0; break; + case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break; + // center + default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break; + } + + switch(edge.y){ + case 'top': edgeOffset.y = 0; break; + case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break; + // center + default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break; + } + + position.x += edgeOffset.x; + position.y += edgeOffset.y; + }, + + getCoordinateFromValue: function(option){ + if (typeOf(option) != 'string') return option; + option = option.toLowerCase(); + + return { + x: option.test('left') ? 'left' + : (option.test('right') ? 'right' : 'center'), + y: option.test(/upper|top/) ? 'top' + : (option.test('bottom') ? 'bottom' : 'center') + }; + } + +}; + +Element.implement({ + + position: function(options){ + if (options && (options.x != null || options.y != null)){ + return (original ? original.apply(this, arguments) : this); + } + var position = this.setStyle('position', 'absolute').calculatePosition(options); + return (options && options.returnPos) ? position : this.setStyles(position); + }, + + calculatePosition: function(options){ + return local.getPosition(this, options); + } + +}); + +})(Element.prototype.position); + + +/* +--- + +script: IframeShim.js + +name: IframeShim + +description: Defines IframeShim, a class for obscuring select lists and flash objects in IE. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Event + - Core/Element.Style + - Core/Options + - Core/Events + - Element.Position + - Class.Occlude + +provides: [IframeShim] + +... +*/ + +(function(){ + +var browsers = false; + + +this.IframeShim = new Class({ + + Implements: [Options, Events, Class.Occlude], + + options: { + className: 'iframeShim', + src: 'javascript:false;document.write("");', + display: false, + zIndex: null, + margin: 0, + offset: {x: 0, y: 0}, + browsers: browsers + }, + + property: 'IframeShim', + + initialize: function(element, options){ + this.element = document.id(element); + if (this.occlude()) return this.occluded; + this.setOptions(options); + this.makeShim(); + return this; + }, + + makeShim: function(){ + if (this.options.browsers){ + var zIndex = this.element.getStyle('zIndex').toInt(); + + if (!zIndex){ + zIndex = 1; + var pos = this.element.getStyle('position'); + if (pos == 'static' || !pos) this.element.setStyle('position', 'relative'); + this.element.setStyle('zIndex', zIndex); + } + zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1; + if (zIndex < 0) zIndex = 1; + this.shim = new Element('iframe', { + src: this.options.src, + scrolling: 'no', + frameborder: 0, + styles: { + zIndex: zIndex, + position: 'absolute', + border: 'none', + filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)' + }, + 'class': this.options.className + }).store('IframeShim', this); + var inject = (function(){ + this.shim.inject(this.element, 'after'); + this[this.options.display ? 'show' : 'hide'](); + this.fireEvent('inject'); + }).bind(this); + if (!IframeShim.ready) window.addEvent('load', inject); + else inject(); + } else { + this.position = this.hide = this.show = this.dispose = Function.from(this); + } + }, + + position: function(){ + if (!IframeShim.ready || !this.shim) return this; + var size = this.element.measure(function(){ + return this.getSize(); + }); + if (this.options.margin != undefined){ + size.x = size.x - (this.options.margin * 2); + size.y = size.y - (this.options.margin * 2); + this.options.offset.x += this.options.margin; + this.options.offset.y += this.options.margin; + } + this.shim.set({width: size.x, height: size.y}).position({ + relativeTo: this.element, + offset: this.options.offset + }); + return this; + }, + + hide: function(){ + if (this.shim) this.shim.setStyle('display', 'none'); + return this; + }, + + show: function(){ + if (this.shim) this.shim.setStyle('display', 'block'); + return this.position(); + }, + + dispose: function(){ + if (this.shim) this.shim.dispose(); + return this; + }, + + destroy: function(){ + if (this.shim) this.shim.destroy(); + return this; + } + +}); + +})(); + +window.addEvent('load', function(){ + IframeShim.ready = true; +}); + + +/* +--- + +script: Mask.js + +name: Mask + +description: Creates a mask element to cover another. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Options + - Core/Events + - Core/Element.Event + - Class.Binds + - Element.Position + - IframeShim + +provides: [Mask] + +... +*/ + +var Mask = new Class({ + + Implements: [Options, Events], + + Binds: ['position'], + + options: {/* + onShow: function(){}, + onHide: function(){}, + onDestroy: function(){}, + onClick: function(event){}, + inject: { + where: 'after', + target: null, + }, + hideOnClick: false, + id: null, + destroyOnHide: false,*/ + style: {}, + 'class': 'mask', + maskMargins: false, + useIframeShim: true, + iframeShimOptions: {} + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('mask', this); + this.setOptions(options); + this.render(); + this.inject(); + }, + + render: function(){ + this.element = new Element('div', { + 'class': this.options['class'], + id: this.options.id || 'mask-' + String.uniqueID(), + styles: Object.merge({}, this.options.style, { + display: 'none' + }), + events: { + click: function(event){ + this.fireEvent('click', event); + if (this.options.hideOnClick) this.hide(); + }.bind(this) + } + }); + + this.hidden = true; + }, + + toElement: function(){ + return this.element; + }, + + inject: function(target, where){ + where = where || (this.options.inject ? this.options.inject.where : '') || (this.target == document.body ? 'inside' : 'after'); + target = target || (this.options.inject && this.options.inject.target) || this.target; + + this.element.inject(target, where); + + if (this.options.useIframeShim){ + this.shim = new IframeShim(this.element, this.options.iframeShimOptions); + + this.addEvents({ + show: this.shim.show.bind(this.shim), + hide: this.shim.hide.bind(this.shim), + destroy: this.shim.destroy.bind(this.shim) + }); + } + }, + + position: function(){ + this.resize(this.options.width, this.options.height); + + this.element.position({ + relativeTo: this.target, + position: 'topLeft', + ignoreMargins: !this.options.maskMargins, + ignoreScroll: this.target == document.body + }); + + return this; + }, + + resize: function(x, y){ + var opt = { + styles: ['padding', 'border'] + }; + if (this.options.maskMargins) opt.styles.push('margin'); + + var dim = this.target.getComputedSize(opt); + if (this.target == document.body){ + this.element.setStyles({width: 0, height: 0}); + var win = window.getScrollSize(); + if (dim.totalHeight < win.y) dim.totalHeight = win.y; + if (dim.totalWidth < win.x) dim.totalWidth = win.x; + } + this.element.setStyles({ + width: Array.pick([x, dim.totalWidth, dim.x]), + height: Array.pick([y, dim.totalHeight, dim.y]) + }); + + return this; + }, + + show: function(){ + if (!this.hidden) return this; + + window.addEvent('resize', this.position); + this.position(); + this.showMask.apply(this, arguments); + + return this; + }, + + showMask: function(){ + this.element.setStyle('display', 'block'); + this.hidden = false; + this.fireEvent('show'); + }, + + hide: function(){ + if (this.hidden) return this; + + window.removeEvent('resize', this.position); + this.hideMask.apply(this, arguments); + if (this.options.destroyOnHide) return this.destroy(); + + return this; + }, + + hideMask: function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + }, + + toggle: function(){ + this[this.hidden ? 'show' : 'hide'](); + }, + + destroy: function(){ + this.hide(); + this.element.destroy(); + this.fireEvent('destroy'); + this.target.eliminate('mask'); + } + +}); + +Element.Properties.mask = { + + set: function(options){ + var mask = this.retrieve('mask'); + if (mask) mask.destroy(); + return this.eliminate('mask').store('mask:options', options); + }, + + get: function(){ + var mask = this.retrieve('mask'); + if (!mask){ + mask = new Mask(this, this.retrieve('mask:options')); + this.store('mask', mask); + } + return mask; + } + +}; + +Element.implement({ + + mask: function(options){ + if (options) this.set('mask', options); + this.get('mask').show(); + return this; + }, + + unmask: function(){ + this.get('mask').hide(); + return this; + } + +}); + + +/* +--- + +script: Spinner.js + +name: Spinner + +description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Tween + - Core/Request + - Class.refactor + - Mask + +provides: [Spinner] + +... +*/ + +var Spinner = new Class({ + + Extends: Mask, + + Implements: Chain, + + options: {/* + message: false,*/ + 'class': 'spinner', + containerPosition: {}, + content: { + 'class': 'spinner-content' + }, + messageContainer: { + 'class': 'spinner-msg' + }, + img: { + 'class': 'spinner-img' + }, + fxOptions: { + link: 'chain' + } + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('spinner', this); + this.setOptions(options); + this.render(); + this.inject(); + + // Add this to events for when noFx is true; parent methods handle hide/show. + var deactivate = function(){ this.active = false; }.bind(this); + this.addEvents({ + hide: deactivate, + show: deactivate + }); + }, + + render: function(){ + this.parent(); + + this.element.set('id', this.options.id || 'spinner-' + String.uniqueID()); + + this.content = document.id(this.options.content) || new Element('div', this.options.content); + this.content.inject(this.element); + + if (this.options.message){ + this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message); + this.msg.inject(this.content); + } + + if (this.options.img){ + this.img = document.id(this.options.img) || new Element('div', this.options.img); + this.img.inject(this.content); + } + + this.element.set('tween', this.options.fxOptions); + }, + + show: function(noFx){ + if (this.active) return this.chain(this.show.bind(this)); + if (!this.hidden){ + this.callChain.delay(20, this); + return this; + } + + this.target.set('aria-busy', 'true'); + this.active = true; + + return this.parent(noFx); + }, + + showMask: function(noFx){ + var pos = function(){ + this.content.position(Object.merge({ + relativeTo: this.element + }, this.options.containerPosition)); + }.bind(this); + + if (noFx){ + this.parent(); + pos(); + } else { + if (!this.options.style.opacity) this.options.style.opacity = this.element.getStyle('opacity').toFloat(); + this.element.setStyles({ + display: 'block', + opacity: 0 + }).tween('opacity', this.options.style.opacity); + pos(); + this.hidden = false; + this.fireEvent('show'); + this.callChain(); + } + }, + + hide: function(noFx){ + if (this.active) return this.chain(this.hide.bind(this)); + if (this.hidden){ + this.callChain.delay(20, this); + return this; + } + + this.target.set('aria-busy', 'false'); + this.active = true; + + return this.parent(noFx); + }, + + hideMask: function(noFx){ + if (noFx) return this.parent(); + this.element.tween('opacity', 0).get('tween').chain(function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + this.callChain(); + }.bind(this)); + }, + + destroy: function(){ + this.content.destroy(); + this.parent(); + this.target.eliminate('spinner'); + } + +}); + +Request = Class.refactor(Request, { + + options: { + useSpinner: false, + spinnerOptions: {}, + spinnerTarget: false + }, + + initialize: function(options){ + this._send = this.send; + this.send = function(options){ + var spinner = this.getSpinner(); + if (spinner) spinner.chain(this._send.pass(options, this)).show(); + else this._send(options); + return this; + }; + this.previous(options); + }, + + getSpinner: function(){ + if (!this.spinner){ + var update = document.id(this.options.spinnerTarget) || document.id(this.options.update); + if (this.options.useSpinner && update){ + update.set('spinner', this.options.spinnerOptions); + var spinner = this.spinner = update.get('spinner'); + ['complete', 'exception', 'cancel'].each(function(event){ + this.addEvent(event, spinner.hide.bind(spinner)); + }, this); + } + } + return this.spinner; + } + +}); + +Element.Properties.spinner = { + + set: function(options){ + var spinner = this.retrieve('spinner'); + if (spinner) spinner.destroy(); + return this.eliminate('spinner').store('spinner:options', options); + }, + + get: function(){ + var spinner = this.retrieve('spinner'); + if (!spinner){ + spinner = new Spinner(this, this.retrieve('spinner:options')); + this.store('spinner', spinner); + } + return spinner; + } + +}; + +Element.implement({ + + spin: function(options){ + if (options) this.set('spinner', options); + this.get('spinner').show(); + return this; + }, + + unspin: function(){ + this.get('spinner').hide(); + return this; + } + +}); + + +/* +--- + +script: String.QueryString.js + +name: String.QueryString + +description: Methods for dealing with URI query strings. + +license: MIT-style license + +authors: + - Sebastian Markbåge + - Aaron Newton + - Lennart Pilon + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - MooTools.More + +provides: [String.QueryString] + +... +*/ + +String.implement({ + + parseQueryString: function(decodeKeys, decodeValues){ + if (decodeKeys == null) decodeKeys = true; + if (decodeValues == null) decodeValues = true; + + var vars = this.split(/[&;]/), + object = {}; + if (!vars.length) return object; + + vars.each(function(val){ + var index = val.indexOf('=') + 1, + value = index ? val.substr(index) : '', + keys = index ? val.substr(0, index - 1).match(/([^\]\[]+|(\B)(?=\]))/g) : [val], + obj = object; + if (!keys) return; + if (decodeValues) value = decodeURIComponent(value); + keys.each(function(key, i){ + if (decodeKeys) key = decodeURIComponent(key); + var current = obj[key]; + + if (i < keys.length - 1) obj = obj[key] = current || {}; + else if (typeOf(current) == 'array') current.push(value); + else obj[key] = current != null ? [current, value] : value; + }); + }); + + return object; + }, + + cleanQueryString: function(method){ + return this.split('&').filter(function(val){ + var index = val.indexOf('='), + key = index < 0 ? '' : val.substr(0, index), + value = val.substr(index + 1); + + return method ? method.call(null, key, value) : (value || value === 0); + }).join('&'); + } + +}); + + +/* +--- + +name: Events.Pseudos + +description: Adds the functionality to add pseudo events + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Class.Extras, Core/Slick.Parser, MooTools.More] + +provides: [Events.Pseudos] + +... +*/ + +(function(){ + +Events.Pseudos = function(pseudos, addEvent, removeEvent){ + + var storeKey = '_monitorEvents:'; + + var storageOf = function(object){ + return { + store: object.store ? function(key, value){ + object.store(storeKey + key, value); + } : function(key, value){ + (object._monitorEvents || (object._monitorEvents = {}))[key] = value; + }, + retrieve: object.retrieve ? function(key, dflt){ + return object.retrieve(storeKey + key, dflt); + } : function(key, dflt){ + if (!object._monitorEvents) return dflt; + return object._monitorEvents[key] || dflt; + } + }; + }; + + var splitType = function(type){ + if (type.indexOf(':') == -1 || !pseudos) return null; + + var parsed = Slick.parse(type).expressions[0][0], + parsedPseudos = parsed.pseudos, + l = parsedPseudos.length, + splits = []; + + while (l--){ + var pseudo = parsedPseudos[l].key, + listener = pseudos[pseudo]; + if (listener != null) splits.push({ + event: parsed.tag, + value: parsedPseudos[l].value, + pseudo: pseudo, + original: type, + listener: listener + }); + } + return splits.length ? splits : null; + }; + + return { + + addEvent: function(type, fn, internal){ + var split = splitType(type); + if (!split) return addEvent.call(this, type, fn, internal); + + var storage = storageOf(this), + events = storage.retrieve(type, []), + eventType = split[0].event, + args = Array.slice(arguments, 2), + stack = fn, + self = this; + + split.each(function(item){ + var listener = item.listener, + stackFn = stack; + if (listener == false) eventType += ':' + item.pseudo + '(' + item.value + ')'; + else stack = function(){ + listener.call(self, item, stackFn, arguments, stack); + }; + }); + + events.include({type: eventType, event: fn, monitor: stack}); + storage.store(type, events); + + if (type != eventType) addEvent.apply(this, [type, fn].concat(args)); + return addEvent.apply(this, [eventType, stack].concat(args)); + }, + + removeEvent: function(type, fn){ + var split = splitType(type); + if (!split) return removeEvent.call(this, type, fn); + + var storage = storageOf(this), + events = storage.retrieve(type); + if (!events) return this; + + var args = Array.slice(arguments, 2); + + removeEvent.apply(this, [type, fn].concat(args)); + events.each(function(monitor, i){ + if (!fn || monitor.event == fn) removeEvent.apply(this, [monitor.type, monitor.monitor].concat(args)); + delete events[i]; + }, this); + + storage.store(type, events); + return this; + } + + }; + +}; + +var pseudos = { + + once: function(split, fn, args, monitor){ + fn.apply(this, args); + this.removeEvent(split.event, monitor) + .removeEvent(split.original, fn); + }, + + throttle: function(split, fn, args){ + if (!fn._throttled){ + fn.apply(this, args); + fn._throttled = setTimeout(function(){ + fn._throttled = false; + }, split.value || 250); + } + }, + + pause: function(split, fn, args){ + clearTimeout(fn._pause); + fn._pause = fn.delay(split.value || 250, this, args); + } + +}; + +Events.definePseudo = function(key, listener){ + pseudos[key] = listener; + return this; +}; + +Events.lookupPseudo = function(key){ + return pseudos[key]; +}; + +var proto = Events.prototype; +Events.implement(Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +['Request', 'Fx'].each(function(klass){ + if (this[klass]) this[klass].implement(Events.prototype); +}); + +})(); + + +/* +--- + +name: Element.Event.Pseudos + +description: Adds the functionality to add pseudo events for Elements + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Element.Event, Core/Element.Delegation, Events.Pseudos] + +provides: [Element.Event.Pseudos, Element.Delegation.Pseudo] + +... +*/ + +(function(){ + +var pseudos = {relay: false}, + copyFromEvents = ['once', 'throttle', 'pause'], + count = copyFromEvents.length; + +while (count--) pseudos[copyFromEvents[count]] = Events.lookupPseudo(copyFromEvents[count]); + +DOMEvent.definePseudo = function(key, listener){ + pseudos[key] = listener; + return this; +}; + +var proto = Element.prototype; +[Element, Window, Document].invoke('implement', Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +})(); + + +/* +--- + +script: Form.Request.js + +name: Form.Request + +description: Handles the basic functionality of submitting a form and updating a dom element with the result. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Request.HTML + - Class.Binds + - Class.Occlude + - Spinner + - String.QueryString + - Element.Delegation.Pseudo + +provides: [Form.Request] + +... +*/ + +if (!window.Form) window.Form = {}; + +(function(){ + + Form.Request = new Class({ + + Binds: ['onSubmit', 'onFormValidate'], + + Implements: [Options, Events, Class.Occlude], + + options: {/* + onFailure: function(){}, + onSuccess: function(){}, // aliased to onComplete, + onSend: function(){}*/ + requestOptions: { + evalScripts: true, + useSpinner: true, + emulation: false, + link: 'ignore' + }, + sendButtonClicked: true, + extraData: {}, + resetForm: true + }, + + property: 'form.request', + + initialize: function(form, target, options){ + this.element = document.id(form); + if (this.occlude()) return this.occluded; + this.setOptions(options) + .setTarget(target) + .attach(); + }, + + setTarget: function(target){ + this.target = document.id(target); + if (!this.request){ + this.makeRequest(); + } else { + this.request.setOptions({ + update: this.target + }); + } + return this; + }, + + toElement: function(){ + return this.element; + }, + + makeRequest: function(){ + var self = this; + this.request = new Request.HTML(Object.merge({ + update: this.target, + emulation: false, + spinnerTarget: this.element, + method: this.element.get('method') || 'post' + }, this.options.requestOptions)).addEvents({ + success: function(tree, elements, html, javascript){ + ['complete', 'success'].each(function(evt){ + self.fireEvent(evt, [self.target, tree, elements, html, javascript]); + }); + }, + failure: function(){ + self.fireEvent('complete', arguments).fireEvent('failure', arguments); + }, + exception: function(){ + self.fireEvent('failure', arguments); + } + }); + return this.attachReset(); + }, + + attachReset: function(){ + if (!this.options.resetForm) return this; + this.request.addEvent('success', function(){ + Function.attempt(function(){ + this.element.reset(); + }.bind(this)); + if (window.OverText) OverText.update(); + }.bind(this)); + return this; + }, + + attach: function(attach){ + var method = (attach != false) ? 'addEvent' : 'removeEvent'; + this.element[method]('click:relay(button, input[type=submit])', this.saveClickedButton.bind(this)); + + var fv = this.element.retrieve('validator'); + if (fv) fv[method]('onFormValidate', this.onFormValidate); + else this.element[method]('submit', this.onSubmit); + + return this; + }, + + detach: function(){ + return this.attach(false); + }, + + //public method + enable: function(){ + return this.attach(); + }, + + //public method + disable: function(){ + return this.detach(); + }, + + onFormValidate: function(valid, form, event){ + //if there's no event, then this wasn't a submit event + if (!event) return; + var fv = this.element.retrieve('validator'); + if (valid || (fv && !fv.options.stopOnFailure)){ + event.stop(); + this.send(); + } + }, + + onSubmit: function(event){ + var fv = this.element.retrieve('validator'); + if (fv){ + //form validator was created after Form.Request + this.element.removeEvent('submit', this.onSubmit); + fv.addEvent('onFormValidate', this.onFormValidate); + fv.validate(event); + return; + } + if (event) event.stop(); + this.send(); + }, + + saveClickedButton: function(event, target){ + var targetName = target.get('name'); + if (!targetName || !this.options.sendButtonClicked) return; + this.options.extraData[targetName] = target.get('value') || true; + this.clickedCleaner = function(){ + delete this.options.extraData[targetName]; + this.clickedCleaner = function(){}; + }.bind(this); + }, + + clickedCleaner: function(){}, + + send: function(){ + var str = this.element.toQueryString().trim(), + data = Object.toQueryString(this.options.extraData); + + if (str) str += "&" + data; + else str = data; + + this.fireEvent('send', [this.element, str.parseQueryString()]); + this.request.send({ + data: str, + url: this.options.requestOptions.url || this.element.get('action') + }); + this.clickedCleaner(); + return this; + } + + }); + + Element.implement('formUpdate', function(update, options){ + var fq = this.retrieve('form.request'); + if (!fq){ + fq = new Form.Request(this, update, options); + } else { + if (update) fq.setTarget(update); + if (options) fq.setOptions(options).makeRequest(); + } + fq.send(); + return this; + }); + +})(); + + +/* +--- + +script: Element.Shortcuts.js + +name: Element.Shortcuts + +description: Extends the Element native object to include some shortcut methods. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - MooTools.More + +provides: [Element.Shortcuts] + +... +*/ + +Element.implement({ + + isDisplayed: function(){ + return this.getStyle('display') != 'none'; + }, + + isVisible: function(){ + var w = this.offsetWidth, + h = this.offsetHeight; + return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.style.display != 'none'; + }, + + toggle: function(){ + return this[this.isDisplayed() ? 'hide' : 'show'](); + }, + + hide: function(){ + var d; + try { + //IE fails here if the element is not in the dom + d = this.getStyle('display'); + } catch(e){} + if (d == 'none') return this; + return this.store('element:_originalDisplay', d || '').setStyle('display', 'none'); + }, + + show: function(display){ + if (!display && this.isDisplayed()) return this; + display = display || this.retrieve('element:_originalDisplay') || 'block'; + return this.setStyle('display', (display == 'none') ? 'block' : display); + }, + + swapClass: function(remove, add){ + return this.removeClass(remove).addClass(add); + } + +}); + +Document.implement({ + + clearSelection: function(){ + if (window.getSelection){ + var selection = window.getSelection(); + if (selection && selection.removeAllRanges) selection.removeAllRanges(); + } else if (document.selection && document.selection.empty){ + try { + //IE fails here if selected element is not in dom + document.selection.empty(); + } catch(e){} + } + } + +}); + + +/* +--- + +script: Fx.Reveal.js + +name: Fx.Reveal + +description: Defines Fx.Reveal, a class that shows and hides elements with a transition. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Morph + - Element.Shortcuts + - Element.Measure + +provides: [Fx.Reveal] + +... +*/ + +(function(){ + + +var hideTheseOf = function(object){ + var hideThese = object.options.hideInputs; + if (window.OverText){ + var otClasses = [null]; + OverText.each(function(ot){ + otClasses.include('.' + ot.options.labelClass); + }); + if (otClasses) hideThese += otClasses.join(', '); + } + return (hideThese) ? object.element.getElements(hideThese) : null; +}; + + +Fx.Reveal = new Class({ + + Extends: Fx.Morph, + + options: {/* + onShow: function(thisElement){}, + onHide: function(thisElement){}, + onComplete: function(thisElement){}, + heightOverride: null, + widthOverride: null,*/ + link: 'cancel', + styles: ['padding', 'border', 'margin'], + transitionOpacity: 'opacity' in document.documentElement, + mode: 'vertical', + display: function(){ + return this.element.get('tag') != 'tr' ? 'block' : 'table-row'; + }, + opacity: 1, + hideInputs: !('opacity' in document.documentElement) ? 'select, input, textarea, object, embed' : null + }, + + dissolve: function(){ + if (!this.hiding && !this.showing){ + if (this.element.getStyle('display') != 'none'){ + this.hiding = true; + this.showing = false; + this.hidden = true; + this.cssText = this.element.style.cssText; + + var startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + if (this.options.transitionOpacity) startStyles.opacity = this.options.opacity; + + var zero = {}; + Object.each(startStyles, function(style, name){ + zero[name] = [style, 0]; + }); + + this.element.setStyles({ + display: Function.from(this.options.display).call(this), + overflow: 'hidden' + }); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + if (this.hidden){ + this.hiding = false; + this.element.style.cssText = this.cssText; + this.element.setStyle('display', 'none'); + if (hideThese) hideThese.setStyle('visibility', 'visible'); + } + this.fireEvent('hide', this.element); + this.callChain(); + }.bind(this)); + + this.start(zero); + } else { + this.callChain.delay(10, this); + this.fireEvent('complete', this.element); + this.fireEvent('hide', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.dissolve.bind(this)); + } else if (this.options.link == 'cancel' && !this.hiding){ + this.cancel(); + this.dissolve(); + } + return this; + }, + + reveal: function(){ + if (!this.showing && !this.hiding){ + if (this.element.getStyle('display') == 'none'){ + this.hiding = false; + this.showing = true; + this.hidden = false; + this.cssText = this.element.style.cssText; + + var startStyles; + this.element.measure(function(){ + startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + }.bind(this)); + if (this.options.heightOverride != null) startStyles.height = this.options.heightOverride.toInt(); + if (this.options.widthOverride != null) startStyles.width = this.options.widthOverride.toInt(); + if (this.options.transitionOpacity){ + this.element.setStyle('opacity', 0); + startStyles.opacity = this.options.opacity; + } + + var zero = { + height: 0, + display: Function.from(this.options.display).call(this) + }; + Object.each(startStyles, function(style, name){ + zero[name] = 0; + }); + zero.overflow = 'hidden'; + + this.element.setStyles(zero); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + this.element.style.cssText = this.cssText; + this.element.setStyle('display', Function.from(this.options.display).call(this)); + if (!this.hidden) this.showing = false; + if (hideThese) hideThese.setStyle('visibility', 'visible'); + this.callChain(); + this.fireEvent('show', this.element); + }.bind(this)); + + this.start(startStyles); + } else { + this.callChain(); + this.fireEvent('complete', this.element); + this.fireEvent('show', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.reveal.bind(this)); + } else if (this.options.link == 'cancel' && !this.showing){ + this.cancel(); + this.reveal(); + } + return this; + }, + + toggle: function(){ + if (this.element.getStyle('display') == 'none'){ + this.reveal(); + } else { + this.dissolve(); + } + return this; + }, + + cancel: function(){ + this.parent.apply(this, arguments); + if (this.cssText != null) this.element.style.cssText = this.cssText; + this.hiding = false; + this.showing = false; + return this; + } + +}); + +Element.Properties.reveal = { + + set: function(options){ + this.get('reveal').cancel().setOptions(options); + return this; + }, + + get: function(){ + var reveal = this.retrieve('reveal'); + if (!reveal){ + reveal = new Fx.Reveal(this); + this.store('reveal', reveal); + } + return reveal; + } + +}; + +Element.Properties.dissolve = Element.Properties.reveal; + +Element.implement({ + + reveal: function(options){ + this.get('reveal').setOptions(options).reveal(); + return this; + }, + + dissolve: function(options){ + this.get('reveal').setOptions(options).dissolve(); + return this; + }, + + nix: function(options){ + var params = Array.link(arguments, {destroy: Type.isBoolean, options: Type.isObject}); + this.get('reveal').setOptions(options).dissolve().chain(function(){ + this[params.destroy ? 'destroy' : 'dispose'](); + }.bind(this)); + return this; + }, + + wink: function(){ + var params = Array.link(arguments, {duration: Type.isNumber, options: Type.isObject}); + var reveal = this.get('reveal').setOptions(params.options); + reveal.reveal().chain(function(){ + (function(){ + reveal.dissolve(); + }).delay(params.duration || 2000); + }); + } + +}); + +})(); + + +/* +--- + +script: Drag.js + +name: Drag + +description: The base Drag Class. Can be used to drag and resize Elements using mouse events. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + +requires: + - Core/Events + - Core/Options + - Core/Element.Event + - Core/Element.Style + - Core/Element.Dimensions + - MooTools.More + +provides: [Drag] +... + +*/ + +var Drag = new Class({ + + Implements: [Events, Options], + + options: {/* + onBeforeStart: function(thisElement){}, + onStart: function(thisElement, event){}, + onSnap: function(thisElement){}, + onDrag: function(thisElement, event){}, + onCancel: function(thisElement){}, + onComplete: function(thisElement, event){},*/ + snap: 6, + unit: 'px', + grid: false, + style: true, + limit: false, + handle: false, + invert: false, + preventDefault: false, + stopPropagation: false, + modifiers: {x: 'left', y: 'top'} + }, + + initialize: function(){ + var params = Array.link(arguments, { + 'options': Type.isObject, + 'element': function(obj){ + return obj != null; + } + }); + + this.element = document.id(params.element); + this.document = this.element.getDocument(); + this.setOptions(params.options || {}); + var htype = typeOf(this.options.handle); + this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element; + this.mouse = {'now': {}, 'pos': {}}; + this.value = {'start': {}, 'now': {}}; + + this.selection = 'selectstart' in document ? 'selectstart' : 'mousedown'; + + + if ('ondragstart' in document && !('FileReader' in window) && !Drag.ondragstartFixed){ + document.ondragstart = Function.from(false); + Drag.ondragstartFixed = true; + } + + this.bound = { + start: this.start.bind(this), + check: this.check.bind(this), + drag: this.drag.bind(this), + stop: this.stop.bind(this), + cancel: this.cancel.bind(this), + eventStop: Function.from(false) + }; + this.attach(); + }, + + attach: function(){ + this.handles.addEvent('mousedown', this.bound.start); + return this; + }, + + detach: function(){ + this.handles.removeEvent('mousedown', this.bound.start); + return this; + }, + + start: function(event){ + var options = this.options; + + if (event.rightClick) return; + + if (options.preventDefault) event.preventDefault(); + if (options.stopPropagation) event.stopPropagation(); + this.mouse.start = event.page; + + this.fireEvent('beforeStart', this.element); + + var limit = options.limit; + this.limit = {x: [], y: []}; + + var z, coordinates; + for (z in options.modifiers){ + if (!options.modifiers[z]) continue; + + var style = this.element.getStyle(options.modifiers[z]); + + // Some browsers (IE and Opera) don't always return pixels. + if (style && !style.match(/px$/)){ + if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent()); + style = coordinates[options.modifiers[z]]; + } + + if (options.style) this.value.now[z] = (style || 0).toInt(); + else this.value.now[z] = this.element[options.modifiers[z]]; + + if (options.invert) this.value.now[z] *= -1; + + this.mouse.pos[z] = event.page[z] - this.value.now[z]; + + if (limit && limit[z]){ + var i = 2; + while (i--){ + var limitZI = limit[z][i]; + if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI; + } + } + } + + if (typeOf(this.options.grid) == 'number') this.options.grid = { + x: this.options.grid, + y: this.options.grid + }; + + var events = { + mousemove: this.bound.check, + mouseup: this.bound.cancel + }; + events[this.selection] = this.bound.eventStop; + this.document.addEvents(events); + }, + + check: function(event){ + if (this.options.preventDefault) event.preventDefault(); + var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2))); + if (distance > this.options.snap){ + this.cancel(); + this.document.addEvents({ + mousemove: this.bound.drag, + mouseup: this.bound.stop + }); + this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element); + } + }, + + drag: function(event){ + var options = this.options; + + if (options.preventDefault) event.preventDefault(); + this.mouse.now = event.page; + + for (var z in options.modifiers){ + if (!options.modifiers[z]) continue; + this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; + + if (options.invert) this.value.now[z] *= -1; + + if (options.limit && this.limit[z]){ + if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){ + this.value.now[z] = this.limit[z][1]; + } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){ + this.value.now[z] = this.limit[z][0]; + } + } + + if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]); + + if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit); + else this.element[options.modifiers[z]] = this.value.now[z]; + } + + this.fireEvent('drag', [this.element, event]); + }, + + cancel: function(event){ + this.document.removeEvents({ + mousemove: this.bound.check, + mouseup: this.bound.cancel + }); + if (event){ + this.document.removeEvent(this.selection, this.bound.eventStop); + this.fireEvent('cancel', this.element); + } + }, + + stop: function(event){ + var events = { + mousemove: this.bound.drag, + mouseup: this.bound.stop + }; + events[this.selection] = this.bound.eventStop; + this.document.removeEvents(events); + if (event) this.fireEvent('complete', [this.element, event]); + } + +}); + +Element.implement({ + + makeResizable: function(options){ + var drag = new Drag(this, Object.merge({ + modifiers: { + x: 'width', + y: 'height' + } + }, options)); + + this.store('resizer', drag); + return drag.addEvent('drag', function(){ + this.fireEvent('resize', drag); + }.bind(this)); + } + +}); + + +/* +--- + +script: Drag.Move.js + +name: Drag.Move + +description: A Drag extension that provides support for the constraining of draggables to containers and droppables. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + - Aaron Newton + - Scott Kyle + +requires: + - Core/Element.Dimensions + - Drag + +provides: [Drag.Move] + +... +*/ + +Drag.Move = new Class({ + + Extends: Drag, + + options: {/* + onEnter: function(thisElement, overed){}, + onLeave: function(thisElement, overed){}, + onDrop: function(thisElement, overed, event){},*/ + droppables: [], + container: false, + precalculate: false, + includeMargins: true, + checkDroppables: true + }, + + initialize: function(element, options){ + this.parent(element, options); + element = this.element; + + this.droppables = $$(this.options.droppables); + this.setContainer(this.options.container); + + if (this.options.style){ + if (this.options.modifiers.x == 'left' && this.options.modifiers.y == 'top'){ + var parent = element.getOffsetParent(), + styles = element.getStyles('left', 'top'); + if (parent && (styles.left == 'auto' || styles.top == 'auto')){ + element.setPosition(element.getPosition(parent)); + } + } + + if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute'); + } + + this.addEvent('start', this.checkDroppables, true); + this.overed = null; + }, + + setContainer: function(container) { + this.container = document.id(container); + if (this.container && typeOf(this.container) != 'element'){ + this.container = document.id(this.container.getDocument().body); + } + }, + + start: function(event){ + if (this.container) this.options.limit = this.calculateLimit(); + + if (this.options.precalculate){ + this.positions = this.droppables.map(function(el){ + return el.getCoordinates(); + }); + } + + this.parent(event); + }, + + calculateLimit: function(){ + var element = this.element, + container = this.container, + + offsetParent = document.id(element.getOffsetParent()) || document.body, + containerCoordinates = container.getCoordinates(offsetParent), + elementMargin = {}, + elementBorder = {}, + containerMargin = {}, + containerBorder = {}, + offsetParentPadding = {}; + + ['top', 'right', 'bottom', 'left'].each(function(pad){ + elementMargin[pad] = element.getStyle('margin-' + pad).toInt(); + elementBorder[pad] = element.getStyle('border-' + pad).toInt(); + containerMargin[pad] = container.getStyle('margin-' + pad).toInt(); + containerBorder[pad] = container.getStyle('border-' + pad).toInt(); + offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt(); + }, this); + + var width = element.offsetWidth + elementMargin.left + elementMargin.right, + height = element.offsetHeight + elementMargin.top + elementMargin.bottom, + left = 0, + top = 0, + right = containerCoordinates.right - containerBorder.right - width, + bottom = containerCoordinates.bottom - containerBorder.bottom - height; + + if (this.options.includeMargins){ + left += elementMargin.left; + top += elementMargin.top; + } else { + right += elementMargin.right; + bottom += elementMargin.bottom; + } + + if (element.getStyle('position') == 'relative'){ + var coords = element.getCoordinates(offsetParent); + coords.left -= element.getStyle('left').toInt(); + coords.top -= element.getStyle('top').toInt(); + + left -= coords.left; + top -= coords.top; + if (container.getStyle('position') != 'relative'){ + left += containerBorder.left; + top += containerBorder.top; + } + right += elementMargin.left - coords.left; + bottom += elementMargin.top - coords.top; + + if (container != offsetParent){ + left += containerMargin.left + offsetParentPadding.left; + if (!offsetParentPadding.left && left < 0) left = 0; + top += offsetParent == document.body ? 0 : containerMargin.top + offsetParentPadding.top; + if (!offsetParentPadding.top && top < 0) top = 0; + } + } else { + left -= elementMargin.left; + top -= elementMargin.top; + if (container != offsetParent){ + left += containerCoordinates.left + containerBorder.left; + top += containerCoordinates.top + containerBorder.top; + } + } + + return { + x: [left, right], + y: [top, bottom] + }; + }, + + getDroppableCoordinates: function(element){ + var position = element.getCoordinates(); + if (element.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.left += scroll.x; + position.right += scroll.x; + position.top += scroll.y; + position.bottom += scroll.y; + } + return position; + }, + + checkDroppables: function(){ + var overed = this.droppables.filter(function(el, i){ + el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el); + var now = this.mouse.now; + return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top); + }, this).getLast(); + + if (this.overed != overed){ + if (this.overed) this.fireEvent('leave', [this.element, this.overed]); + if (overed) this.fireEvent('enter', [this.element, overed]); + this.overed = overed; + } + }, + + drag: function(event){ + this.parent(event); + if (this.options.checkDroppables && this.droppables.length) this.checkDroppables(); + }, + + stop: function(event){ + this.checkDroppables(); + this.fireEvent('drop', [this.element, this.overed, event]); + this.overed = null; + return this.parent(event); + } + +}); + +Element.implement({ + + makeDraggable: function(options){ + var drag = new Drag.Move(this, options); + this.store('dragger', drag); + return drag; + } + +}); + + +/* +--- + +script: Sortables.js + +name: Sortables + +description: Class for creating a drag and drop sorting interface for lists of items. + +license: MIT-style license + +authors: + - Tom Occhino + +requires: + - Core/Fx.Morph + - Drag.Move + +provides: [Sortables] + +... +*/ + +var Sortables = new Class({ + + Implements: [Events, Options], + + options: {/* + onSort: function(element, clone){}, + onStart: function(element, clone){}, + onComplete: function(element){},*/ + opacity: 1, + clone: false, + revert: false, + handle: false, + dragOptions: {}, + unDraggableTags: ['button', 'input', 'a', 'textarea', 'select', 'option'] + }, + + initialize: function(lists, options){ + this.setOptions(options); + + this.elements = []; + this.lists = []; + this.idle = true; + + this.addLists($$(document.id(lists) || lists)); + + if (!this.options.clone) this.options.revert = false; + if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({ + duration: 250, + link: 'cancel' + }, this.options.revert)); + }, + + attach: function(){ + this.addLists(this.lists); + return this; + }, + + detach: function(){ + this.lists = this.removeLists(this.lists); + return this; + }, + + addItems: function(){ + Array.flatten(arguments).each(function(element){ + this.elements.push(element); + var start = element.retrieve('sortables:start', function(event){ + this.start.call(this, event, element); + }.bind(this)); + (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start); + }, this); + return this; + }, + + addLists: function(){ + Array.flatten(arguments).each(function(list){ + this.lists.include(list); + this.addItems(list.getChildren()); + }, this); + return this; + }, + + removeItems: function(){ + return $$(Array.flatten(arguments).map(function(element){ + this.elements.erase(element); + var start = element.retrieve('sortables:start'); + (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start); + + return element; + }, this)); + }, + + removeLists: function(){ + return $$(Array.flatten(arguments).map(function(list){ + this.lists.erase(list); + this.removeItems(list.getChildren()); + + return list; + }, this)); + }, + + getDroppableCoordinates: function (element){ + var offsetParent = element.getOffsetParent(); + var position = element.getPosition(offsetParent); + var scroll = { + w: window.getScroll(), + offsetParent: offsetParent.getScroll() + }; + position.x += scroll.offsetParent.x; + position.y += scroll.offsetParent.y; + + if (offsetParent.getStyle('position') == 'fixed'){ + position.x -= scroll.w.x; + position.y -= scroll.w.y; + } + + return position; + }, + + getClone: function(event, element){ + if (!this.options.clone) return new Element(element.tagName).inject(document.body); + if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list); + var clone = element.clone(true).setStyles({ + margin: 0, + position: 'absolute', + visibility: 'hidden', + width: element.getStyle('width') + }).addEvent('mousedown', function(event){ + element.fireEvent('mousedown', event); + }); + //prevent the duplicated radio inputs from unchecking the real one + if (clone.get('html').test('radio')){ + clone.getElements('input[type=radio]').each(function(input, i){ + input.set('name', 'clone_' + i); + if (input.get('checked')) element.getElements('input[type=radio]')[i].set('checked', true); + }); + } + + return clone.inject(this.list).setPosition(this.getDroppableCoordinates(this.element)); + }, + + getDroppables: function(){ + var droppables = this.list.getChildren().erase(this.clone).erase(this.element); + if (!this.options.constrain) droppables.append(this.lists).erase(this.list); + return droppables; + }, + + insert: function(dragging, element){ + var where = 'inside'; + if (this.lists.contains(element)){ + this.list = element; + this.drag.droppables = this.getDroppables(); + } else { + where = this.element.getAllPrevious().contains(element) ? 'before' : 'after'; + } + this.element.inject(element, where); + this.fireEvent('sort', [this.element, this.clone]); + }, + + start: function(event, element){ + if ( + !this.idle || + event.rightClick || + (!this.options.handle && this.options.unDraggableTags.contains(event.target.get('tag'))) + ) return; + + this.idle = false; + this.element = element; + this.opacity = element.getStyle('opacity'); + this.list = element.getParent(); + this.clone = this.getClone(event, element); + + this.drag = new Drag.Move(this.clone, Object.merge({ + + droppables: this.getDroppables() + }, this.options.dragOptions)).addEvents({ + onSnap: function(){ + event.stop(); + this.clone.setStyle('visibility', 'visible'); + this.element.setStyle('opacity', this.options.opacity || 0); + this.fireEvent('start', [this.element, this.clone]); + }.bind(this), + onEnter: this.insert.bind(this), + onCancel: this.end.bind(this), + onComplete: this.end.bind(this) + }); + + this.clone.inject(this.element, 'before'); + this.drag.start(event); + }, + + end: function(){ + this.drag.detach(); + this.element.setStyle('opacity', this.opacity); + var self = this; + if (this.effect){ + var dim = this.element.getStyles('width', 'height'), + clone = this.clone, + pos = clone.computePosition(this.getDroppableCoordinates(clone)); + + var destroy = function(){ + this.removeEvent('cancel', destroy); + clone.destroy(); + self.reset(); + }; + + this.effect.element = clone; + this.effect.start({ + top: pos.top, + left: pos.left, + width: dim.width, + height: dim.height, + opacity: 0.25 + }).addEvent('cancel', destroy).chain(destroy); + } else { + this.clone.destroy(); + self.reset(); + } + + }, + + reset: function(){ + this.idle = true; + this.fireEvent('complete', this.element); + }, + + serialize: function(){ + var params = Array.link(arguments, { + modifier: Type.isFunction, + index: function(obj){ + return obj != null; + } + }); + var serial = this.lists.map(function(list){ + return list.getChildren().map(params.modifier || function(element){ + return element.get('id'); + }, this); + }, this); + + var index = params.index; + if (this.lists.length == 1) index = 0; + return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial; + } + +}); + + +/* +--- + +script: Request.Periodical.js + +name: Request.Periodical + +description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load + +license: MIT-style license + +authors: + - Christoph Pojer + +requires: + - Core/Request + - MooTools.More + +provides: [Request.Periodical] + +... +*/ + +Request.implement({ + + options: { + initialDelay: 5000, + delay: 5000, + limit: 60000 + }, + + startTimer: function(data){ + var fn = function(){ + if (!this.running) this.send({data: data}); + }; + this.lastDelay = this.options.initialDelay; + this.timer = fn.delay(this.lastDelay, this); + this.completeCheck = function(response){ + clearTimeout(this.timer); + this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit); + this.timer = fn.delay(this.lastDelay, this); + }; + return this.addEvent('complete', this.completeCheck); + }, + + stopTimer: function(){ + clearTimeout(this.timer); + return this.removeEvent('complete', this.completeCheck); + } + +}); + + +/* +--- + +script: Color.js + +name: Color + +description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - Core/Number + - Core/Hash + - Core/Function + - MooTools.More + +provides: [Color] + +... +*/ + +(function(){ + +var Color = this.Color = new Type('Color', function(color, type){ + if (arguments.length >= 3){ + type = 'rgb'; color = Array.slice(arguments, 0, 3); + } else if (typeof color == 'string'){ + if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true); + else if (color.match(/hsb/)) color = color.hsbToRgb(); + else color = color.hexToRgb(true); + } + type = type || 'rgb'; + switch (type){ + case 'hsb': + var old = color; + color = color.hsbToRgb(); + color.hsb = old; + break; + case 'hex': color = color.hexToRgb(true); break; + } + color.rgb = color.slice(0, 3); + color.hsb = color.hsb || color.rgbToHsb(); + color.hex = color.rgbToHex(); + return Object.append(color, this); +}); + +Color.implement({ + + mix: function(){ + var colors = Array.slice(arguments); + var alpha = (typeOf(colors.getLast()) == 'number') ? colors.pop() : 50; + var rgb = this.slice(); + colors.each(function(color){ + color = new Color(color); + for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha)); + }); + return new Color(rgb, 'rgb'); + }, + + invert: function(){ + return new Color(this.map(function(value){ + return 255 - value; + })); + }, + + setHue: function(value){ + return new Color([value, this.hsb[1], this.hsb[2]], 'hsb'); + }, + + setSaturation: function(percent){ + return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb'); + }, + + setBrightness: function(percent){ + return new Color([this.hsb[0], this.hsb[1], percent], 'hsb'); + } + +}); + +this.$RGB = function(r, g, b){ + return new Color([r, g, b], 'rgb'); +}; + +this.$HSB = function(h, s, b){ + return new Color([h, s, b], 'hsb'); +}; + +this.$HEX = function(hex){ + return new Color(hex, 'hex'); +}; + +Array.implement({ + + rgbToHsb: function(){ + var red = this[0], + green = this[1], + blue = this[2], + hue = 0; + var max = Math.max(red, green, blue), + min = Math.min(red, green, blue); + var delta = max - min; + var brightness = max / 255, + saturation = (max != 0) ? delta / max : 0; + if (saturation != 0){ + var rr = (max - red) / delta; + var gr = (max - green) / delta; + var br = (max - blue) / delta; + if (red == max) hue = br - gr; + else if (green == max) hue = 2 + rr - br; + else hue = 4 + gr - rr; + hue /= 6; + if (hue < 0) hue++; + } + return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)]; + }, + + hsbToRgb: function(){ + var br = Math.round(this[2] / 100 * 255); + if (this[1] == 0){ + return [br, br, br]; + } else { + var hue = this[0] % 360; + var f = hue % 60; + var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255); + var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255); + var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255); + switch (Math.floor(hue / 60)){ + case 0: return [br, t, p]; + case 1: return [q, br, p]; + case 2: return [p, br, t]; + case 3: return [p, q, br]; + case 4: return [t, p, br]; + case 5: return [br, p, q]; + } + } + return false; + } + +}); + +String.implement({ + + rgbToHsb: function(){ + var rgb = this.match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHsb() : null; + }, + + hsbToRgb: function(){ + var hsb = this.match(/\d{1,3}/g); + return (hsb) ? hsb.hsbToRgb() : null; + } + +}); + +})(); + + diff --git a/module/web/media/js/mootools-more-1.4.0.1.js b/module/webui/themes/dark/js/static/mootools-more.min.js index f3f8e4ee1..ce03a60fd 100644 --- a/module/web/media/js/mootools-more-1.4.0.1.js +++ b/module/webui/themes/dark/js/static/mootools-more.min.js @@ -1,8 +1,13 @@ -// MooTools: the javascript framework. -// Load this file's selection again by visiting: http://mootools.net/more/c1cc18c2fff04bcc58921b4dff80a6f1 -// Or build this file again with packager using: packager build More/Form.Request More/Fx.Reveal More/Sortables More/Request.Periodical More/Color /* --- +MooTools: the javascript framework + +web build: + - http://mootools.net/more/c1cc18c2fff04bcc58921b4dff80a6f1 + +packager build: + - packager build More/Form.Request More/Fx.Reveal More/Sortables More/Request.Periodical More/Color + copyrights: - [MooTools](http://mootools.net) @@ -10,7 +15,8 @@ licenses: - [MIT License](http://mootools.net/license.txt) ... */ -MooTools.More={version:"1.4.0.1",build:"a4244edf2aa97ac8a196fc96082dd35af1abab87"};Class.Mutators.Binds=function(a){if(!this.prototype.initialize){this.implement("initialize",function(){}); + +MooTools.More={version:"1.5.0",build:"73db5e24e6e9c5c87b3a27aebef2248053f7db37"};Class.Mutators.Binds=function(a){if(!this.prototype.initialize){this.implement("initialize",function(){}); }return Array.from(a).concat(this.prototype.Binds||[]);};Class.Mutators.initialize=function(a){return function(){Array.from(this.Binds).each(function(b){var c=this[b]; if(c){this[b]=c.bind(this);}},this);return a.apply(this,arguments);};};Class.Occlude=new Class({occlude:function(c,b){b=document.id(b||this.element);var a=b.retrieve(c||this.property); if(a&&!this.occluded){return(this.occluded=a);}this.occluded=false;b.store(c||this.property,this);return this.occluded;}});Class.refactor=function(b,a){Object.each(a,function(e,d){var c=b.prototype[d]; @@ -28,13 +34,13 @@ if(d.mode=="vertical"){delete e.width;delete d.planes.width;}else{if(d.mode=="ho e["total"+k]=j;i.each(function(m){var l=c(m,g);e["computed"+m.capitalize()]=l;e["total"+k]+=l;});},this);return Object.append(e,g);}});})();(function(b){var a=Element.Position={options:{relativeTo:document.body,position:{x:"center",y:"center"},offset:{x:0,y:0}},getOptions:function(d,c){c=Object.merge({},a.options,c); a.setPositionOption(c);a.setEdgeOption(c);a.setOffsetOption(d,c);a.setDimensionsOption(d,c);return c;},setPositionOption:function(c){c.position=a.getCoordinateFromValue(c.position); },setEdgeOption:function(d){var c=a.getCoordinateFromValue(d.edge);d.edge=c?c:(d.position.x=="center"&&d.position.y=="center")?{x:"center",y:"center"}:{x:"left",y:"top"}; -},setOffsetOption:function(f,d){var c={x:0,y:0},g=f.measure(function(){return document.id(this.getOffsetParent());}),e=g.getScroll();if(!g||g==f.getDocument().body){return; -}c=g.measure(function(){var i=this.getPosition();if(this.getStyle("position")=="fixed"){var h=window.getScroll();i.x+=h.x;i.y+=h.y;}return i;});d.offset={parentPositioned:g!=document.id(d.relativeTo),x:d.offset.x-c.x+e.x,y:d.offset.y-c.y+e.y}; -},setDimensionsOption:function(d,c){c.dimensions=d.getDimensions({computeSize:true,styles:["padding","border","margin"]});},getPosition:function(e,d){var c={}; -d=a.getOptions(e,d);var f=document.id(d.relativeTo)||document.body;a.setPositionCoordinates(d,c,f);if(d.edge){a.toEdge(c,d);}var g=d.offset;c.left=((c.x>=0||g.parentPositioned||d.allowNegative)?c.x:0).toInt(); -c.top=((c.y>=0||g.parentPositioned||d.allowNegative)?c.y:0).toInt();a.toMinMax(c,d);if(d.relFixedPosition||f.getStyle("position")=="fixed"){a.toRelFixedPosition(f,c); -}if(d.ignoreScroll){a.toIgnoreScroll(f,c);}if(d.ignoreMargins){a.toIgnoreMargins(c,d);}c.left=Math.ceil(c.left);c.top=Math.ceil(c.top);delete c.x;delete c.y; -return c;},setPositionCoordinates:function(k,g,d){var f=k.offset.y,h=k.offset.x,e=(d==document.body)?window.getScroll():d.getPosition(),j=e.y,c=e.x,i=window.getSize(); +},setOffsetOption:function(f,d){var c={x:0,y:0};var e={x:0,y:0};var g=f.measure(function(){return document.id(this.getOffsetParent());});if(!g||g==f.getDocument().body){return; +}e=g.getScroll();c=g.measure(function(){var i=this.getPosition();if(this.getStyle("position")=="fixed"){var h=window.getScroll();i.x+=h.x;i.y+=h.y;}return i; +});d.offset={parentPositioned:g!=document.id(d.relativeTo),x:d.offset.x-c.x+e.x,y:d.offset.y-c.y+e.y};},setDimensionsOption:function(d,c){c.dimensions=d.getDimensions({computeSize:true,styles:["padding","border","margin"]}); +},getPosition:function(e,d){var c={};d=a.getOptions(e,d);var f=document.id(d.relativeTo)||document.body;a.setPositionCoordinates(d,c,f);if(d.edge){a.toEdge(c,d); +}var g=d.offset;c.left=((c.x>=0||g.parentPositioned||d.allowNegative)?c.x:0).toInt();c.top=((c.y>=0||g.parentPositioned||d.allowNegative)?c.y:0).toInt(); +a.toMinMax(c,d);if(d.relFixedPosition||f.getStyle("position")=="fixed"){a.toRelFixedPosition(f,c);}if(d.ignoreScroll){a.toIgnoreScroll(f,c);}if(d.ignoreMargins){a.toIgnoreMargins(c,d); +}c.left=Math.ceil(c.left);c.top=Math.ceil(c.top);delete c.x;delete c.y;return c;},setPositionCoordinates:function(k,g,d){var f=k.offset.y,h=k.offset.x,e=(d==document.body)?window.getScroll():d.getPosition(),j=e.y,c=e.x,i=window.getSize(); switch(k.position.x){case"left":g.x=c+h;break;case"right":g.x=c+h+d.offsetWidth;break;default:g.x=c+((d==document.body?i.x:d.offsetWidth)/2)+h;break;}switch(k.position.y){case"top":g.y=j+f; break;case"bottom":g.y=j+f+d.offsetHeight;break;default:g.y=j+((d==document.body?i.y:d.offsetHeight)/2)+f;break;}},toMinMax:function(c,d){var f={left:"x",top:"y"},e; ["minimum","maximum"].each(function(g){["left","top"].each(function(h){e=d[g]?d[g][f[h]]:null;if(e!=null&&((g=="minimum")?c[h]<e:c[h]>e)){c[h]=e;}});}); @@ -45,19 +51,20 @@ c.top+=d.edge.y=="bottom"?d.dimensions["margin-bottom"]:(d.edge.y!="center"?-d.d break;}switch(f.y){case"top":e.y=0;break;case"bottom":e.y=-g.y-g.computedTop-g.computedBottom;break;default:e.y=-(Math.round(g.totalHeight/2));break;}c.x+=e.x; c.y+=e.y;},getCoordinateFromValue:function(c){if(typeOf(c)!="string"){return c;}c=c.toLowerCase();return{x:c.test("left")?"left":(c.test("right")?"right":"center"),y:c.test(/upper|top/)?"top":(c.test("bottom")?"bottom":"center")}; }};Element.implement({position:function(d){if(d&&(d.x!=null||d.y!=null)){return(b?b.apply(this,arguments):this);}var c=this.setStyle("position","absolute").calculatePosition(d); -return(d&&d.returnPos)?c:this.setStyles(c);},calculatePosition:function(c){return a.getPosition(this,c);}});})(Element.prototype.position);var IframeShim=new Class({Implements:[Options,Events,Class.Occlude],options:{className:"iframeShim",src:'javascript:false;document.write("");',display:false,zIndex:null,margin:0,offset:{x:0,y:0},browsers:(Browser.ie6||(Browser.firefox&&Browser.version<3&&Browser.Platform.mac))},property:"IframeShim",initialize:function(b,a){this.element=document.id(b); -if(this.occlude()){return this.occluded;}this.setOptions(a);this.makeShim();return this;},makeShim:function(){if(this.options.browsers){var c=this.element.getStyle("zIndex").toInt(); -if(!c){c=1;var b=this.element.getStyle("position");if(b=="static"||!b){this.element.setStyle("position","relative");}this.element.setStyle("zIndex",c); -}c=((this.options.zIndex!=null||this.options.zIndex===0)&&c>this.options.zIndex)?this.options.zIndex:c-1;if(c<0){c=1;}this.shim=new Element("iframe",{src:this.options.src,scrolling:"no",frameborder:0,styles:{zIndex:c,position:"absolute",border:"none",filter:"progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"},"class":this.options.className}).store("IframeShim",this); -var a=(function(){this.shim.inject(this.element,"after");this[this.options.display?"show":"hide"]();this.fireEvent("inject");}).bind(this);if(!IframeShim.ready){window.addEvent("load",a); -}else{a();}}else{this.position=this.hide=this.show=this.dispose=Function.from(this);}},position:function(){if(!IframeShim.ready||!this.shim){return this; -}var a=this.element.measure(function(){return this.getSize();});if(this.options.margin!=undefined){a.x=a.x-(this.options.margin*2);a.y=a.y-(this.options.margin*2); -this.options.offset.x+=this.options.margin;this.options.offset.y+=this.options.margin;}this.shim.set({width:a.x,height:a.y}).position({relativeTo:this.element,offset:this.options.offset}); +return(d&&d.returnPos)?c:this.setStyles(c);},calculatePosition:function(c){return a.getPosition(this,c);}});})(Element.prototype.position);(function(){var a=false; +this.IframeShim=new Class({Implements:[Options,Events,Class.Occlude],options:{className:"iframeShim",src:'javascript:false;document.write("");',display:false,zIndex:null,margin:0,offset:{x:0,y:0},browsers:a},property:"IframeShim",initialize:function(c,b){this.element=document.id(c); +if(this.occlude()){return this.occluded;}this.setOptions(b);this.makeShim();return this;},makeShim:function(){if(this.options.browsers){var d=this.element.getStyle("zIndex").toInt(); +if(!d){d=1;var c=this.element.getStyle("position");if(c=="static"||!c){this.element.setStyle("position","relative");}this.element.setStyle("zIndex",d); +}d=((this.options.zIndex!=null||this.options.zIndex===0)&&d>this.options.zIndex)?this.options.zIndex:d-1;if(d<0){d=1;}this.shim=new Element("iframe",{src:this.options.src,scrolling:"no",frameborder:0,styles:{zIndex:d,position:"absolute",border:"none",filter:"progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"},"class":this.options.className}).store("IframeShim",this); +var b=(function(){this.shim.inject(this.element,"after");this[this.options.display?"show":"hide"]();this.fireEvent("inject");}).bind(this);if(!IframeShim.ready){window.addEvent("load",b); +}else{b();}}else{this.position=this.hide=this.show=this.dispose=Function.from(this);}},position:function(){if(!IframeShim.ready||!this.shim){return this; +}var b=this.element.measure(function(){return this.getSize();});if(this.options.margin!=undefined){b.x=b.x-(this.options.margin*2);b.y=b.y-(this.options.margin*2); +this.options.offset.x+=this.options.margin;this.options.offset.y+=this.options.margin;}this.shim.set({width:b.x,height:b.y}).position({relativeTo:this.element,offset:this.options.offset}); return this;},hide:function(){if(this.shim){this.shim.setStyle("display","none");}return this;},show:function(){if(this.shim){this.shim.setStyle("display","block"); }return this.position();},dispose:function(){if(this.shim){this.shim.dispose();}return this;},destroy:function(){if(this.shim){this.shim.destroy();}return this; -}});window.addEvent("load",function(){IframeShim.ready=true;});var Mask=new Class({Implements:[Options,Events],Binds:["position"],options:{style:{},"class":"mask",maskMargins:false,useIframeShim:true,iframeShimOptions:{}},initialize:function(b,a){this.target=document.id(b)||document.id(document.body); +}});})();window.addEvent("load",function(){IframeShim.ready=true;});var Mask=new Class({Implements:[Options,Events],Binds:["position"],options:{style:{},"class":"mask",maskMargins:false,useIframeShim:true,iframeShimOptions:{}},initialize:function(b,a){this.target=document.id(b)||document.id(document.body); this.target.store("mask",this);this.setOptions(a);this.render();this.inject();},render:function(){this.element=new Element("div",{"class":this.options["class"],id:this.options.id||"mask-"+String.uniqueID(),styles:Object.merge({},this.options.style,{display:"none"}),events:{click:function(a){this.fireEvent("click",a); -if(this.options.hideOnClick){this.hide();}}.bind(this)}});this.hidden=true;},toElement:function(){return this.element;},inject:function(b,a){a=a||(this.options.inject?this.options.inject.where:"")||this.target==document.body?"inside":"after"; +if(this.options.hideOnClick){this.hide();}}.bind(this)}});this.hidden=true;},toElement:function(){return this.element;},inject:function(b,a){a=a||(this.options.inject?this.options.inject.where:"")||(this.target==document.body?"inside":"after"); b=b||(this.options.inject&&this.options.inject.target)||this.target;this.element.inject(b,a);if(this.options.useIframeShim){this.shim=new IframeShim(this.element,this.options.iframeShimOptions); this.addEvents({show:this.shim.show.bind(this.shim),hide:this.shim.hide.bind(this.shim),destroy:this.shim.destroy.bind(this.shim)});}},position:function(){this.resize(this.options.width,this.options.height); this.element.position({relativeTo:this.target,position:"topLeft",ignoreMargins:!this.options.maskMargins,ignoreScroll:this.target==document.body});return this; @@ -75,10 +82,10 @@ this.target.store("spinner",this);this.setOptions(a);this.render();this.inject() this.content.inject(this.element);if(this.options.message){this.msg=document.id(this.options.message)||new Element("p",this.options.messageContainer).appendText(this.options.message); this.msg.inject(this.content);}if(this.options.img){this.img=document.id(this.options.img)||new Element("div",this.options.img);this.img.inject(this.content); }this.element.set("tween",this.options.fxOptions);},show:function(a){if(this.active){return this.chain(this.show.bind(this));}if(!this.hidden){this.callChain.delay(20,this); -return this;}this.active=true;return this.parent(a);},showMask:function(a){var b=function(){this.content.position(Object.merge({relativeTo:this.element},this.options.containerPosition)); +return this;}this.target.set("aria-busy","true");this.active=true;return this.parent(a);},showMask:function(a){var b=function(){this.content.position(Object.merge({relativeTo:this.element},this.options.containerPosition)); }.bind(this);if(a){this.parent();b();}else{if(!this.options.style.opacity){this.options.style.opacity=this.element.getStyle("opacity").toFloat();}this.element.setStyles({display:"block",opacity:0}).tween("opacity",this.options.style.opacity); b();this.hidden=false;this.fireEvent("show");this.callChain();}},hide:function(a){if(this.active){return this.chain(this.hide.bind(this));}if(this.hidden){this.callChain.delay(20,this); -return this;}this.active=true;return this.parent(a);},hideMask:function(a){if(a){return this.parent();}this.element.tween("opacity",0).get("tween").chain(function(){this.element.setStyle("display","none"); +return this;}this.target.set("aria-busy","false");this.active=true;return this.parent(a);},hideMask:function(a){if(a){return this.parent();}this.element.tween("opacity",0).get("tween").chain(function(){this.element.setStyle("display","none"); this.hidden=true;this.fireEvent("hide");this.callChain();}.bind(this));},destroy:function(){this.content.destroy();this.parent();this.target.eliminate("spinner"); }});Request=Class.refactor(Request,{options:{useSpinner:false,spinnerOptions:{},spinnerTarget:false},initialize:function(a){this._send=this.send;this.send=function(b){var c=this.getSpinner(); if(c){c.chain(this._send.pass(b,this)).show();}else{this._send(b);}return this;};this.previous(a);},getSpinner:function(){if(!this.spinner){var b=document.id(this.options.spinnerTarget)||document.id(this.options.update); @@ -111,7 +118,7 @@ if(this.occlude()){return this.occluded;}this.setOptions(a).setTarget(c).attach( var b=this.element.retrieve("validator");if(b){b[c]("onFormValidate",this.onFormValidate);}else{this.element[c]("submit",this.onSubmit);}return this;},detach:function(){return this.attach(false); },enable:function(){return this.attach();},disable:function(){return this.detach();},onFormValidate:function(c,b,a){if(!a){return;}var d=this.element.retrieve("validator"); if(c||(d&&!d.options.stopOnFailure)){a.stop();this.send();}},onSubmit:function(a){var b=this.element.retrieve("validator");if(b){this.element.removeEvent("submit",this.onSubmit); -b.addEvent("onFormValidate",this.onFormValidate);this.element.validate();return;}if(a){a.stop();}this.send();},saveClickedButton:function(b,c){var a=c.get("name"); +b.addEvent("onFormValidate",this.onFormValidate);b.validate(a);return;}if(a){a.stop();}this.send();},saveClickedButton:function(b,c){var a=c.get("name"); if(!a||!this.options.sendButtonClicked){return;}this.options.extraData[a]=c.get("value")||true;this.clickedCleaner=function(){delete this.options.extraData[a]; this.clickedCleaner=function(){};}.bind(this);},clickedCleaner:function(){},send:function(){var b=this.element.toQueryString().trim(),a=Object.toQueryString(this.options.extraData); if(b){b+="&"+a;}else{b=a;}this.fireEvent("send",[this.element,b.parseQueryString()]);this.request.send({data:b,url:this.options.requestOptions.url||this.element.get("action")}); @@ -123,8 +130,8 @@ this.clickedCleaner();return this;}});Element.implement("formUpdate",function(c, },swapClass:function(a,b){return this.removeClass(a).addClass(b);}});Document.implement({clearSelection:function(){if(window.getSelection){var a=window.getSelection(); if(a&&a.removeAllRanges){a.removeAllRanges();}}else{if(document.selection&&document.selection.empty){try{document.selection.empty();}catch(b){}}}}});(function(){var a=function(d){var b=d.options.hideInputs; if(window.OverText){var c=[null];OverText.each(function(e){c.include("."+e.options.labelClass);});if(c){b+=c.join(", ");}}return(b)?d.element.getElements(b):null; -};Fx.Reveal=new Class({Extends:Fx.Morph,options:{link:"cancel",styles:["padding","border","margin"],transitionOpacity:!Browser.ie6,mode:"vertical",display:function(){return this.element.get("tag")!="tr"?"block":"table-row"; -},opacity:1,hideInputs:Browser.ie?"select, input, textarea, object, embed":null},dissolve:function(){if(!this.hiding&&!this.showing){if(this.element.getStyle("display")!="none"){this.hiding=true; +};Fx.Reveal=new Class({Extends:Fx.Morph,options:{link:"cancel",styles:["padding","border","margin"],transitionOpacity:"opacity" in document.documentElement,mode:"vertical",display:function(){return this.element.get("tag")!="tr"?"block":"table-row"; +},opacity:1,hideInputs:!("opacity" in document.documentElement)?"select, input, textarea, object, embed":null},dissolve:function(){if(!this.hiding&&!this.showing){if(this.element.getStyle("display")!="none"){this.hiding=true; this.showing=false;this.hidden=true;this.cssText=this.element.style.cssText;var d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode}); if(this.options.transitionOpacity){d.opacity=this.options.opacity;}var c={};Object.each(d,function(f,e){c[e]=[f,0];});this.element.setStyles({display:Function.from(this.options.display).call(this),overflow:"hidden"}); var b=a(this);if(b){b.setStyle("visibility","hidden");}this.$chain.unshift(function(){if(this.hidden){this.hiding=false;this.element.style.cssText=this.cssText; @@ -146,7 +153,7 @@ return this;},nix:function(b){var c=Array.link(arguments,{destroy:Type.isBoolean }.bind(this));return this;},wink:function(){var c=Array.link(arguments,{duration:Type.isNumber,options:Type.isObject});var b=this.get("reveal").setOptions(c.options); b.reveal().chain(function(){(function(){b.dissolve();}).delay(c.duration||2000);});}});})();var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var b=Array.link(arguments,{options:Type.isObject,element:function(c){return c!=null; }});this.element=document.id(b.element);this.document=this.element.getDocument();this.setOptions(b.options||{});var a=typeOf(this.options.handle);this.handles=((a=="array"||a=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element; -this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.ie)?"selectstart":"mousedown";if(Browser.ie&&!Drag.ondragstartFixed){document.ondragstart=Function.from(false); +this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection="selectstart" in document?"selectstart":"mousedown";if("ondragstart" in document&&!("FileReader" in window)&&!Drag.ondragstartFixed){document.ondragstart=Function.from(false); Drag.ondragstartFixed=true;}this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:Function.from(false)}; this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start); return this;},start:function(a){var j=this.options;if(a.rightClick){return;}if(j.preventDefault){a.preventDefault();}if(j.stopPropagation){a.stopPropagation(); @@ -164,39 +171,42 @@ this.fireEvent("start",[this.element,a]).fireEvent("snap",this.element);}},drag: if(a){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element);}},stop:function(b){var a={mousemove:this.bound.drag,mouseup:this.bound.stop}; a[this.selection]=this.bound.eventStop;this.document.removeEvents(a);if(b){this.fireEvent("complete",[this.element,b]);}}});Element.implement({makeResizable:function(a){var b=new Drag(this,Object.merge({modifiers:{x:"width",y:"height"}},a)); this.store("resizer",b);return b.addEvent("drag",function(){this.fireEvent("resize",b);}.bind(this));}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false,precalculate:false,includeMargins:true,checkDroppables:true},initialize:function(b,a){this.parent(b,a); -b=this.element;this.droppables=$$(this.options.droppables);this.container=document.id(this.options.container);if(this.container&&typeOf(this.container)!="element"){this.container=document.id(this.container.getDocument().body); -}if(this.options.style){if(this.options.modifiers.x=="left"&&this.options.modifiers.y=="top"){var c=b.getOffsetParent(),d=b.getStyles("left","top");if(c&&(d.left=="auto"||d.top=="auto")){b.setPosition(b.getPosition(c)); -}}if(b.getStyle("position")=="static"){b.setStyle("position","absolute");}}this.addEvent("start",this.checkDroppables,true);this.overed=null;},start:function(a){if(this.container){this.options.limit=this.calculateLimit(); -}if(this.options.precalculate){this.positions=this.droppables.map(function(b){return b.getCoordinates();});}this.parent(a);},calculateLimit:function(){var j=this.element,e=this.container,d=document.id(j.getOffsetParent())||document.body,h=e.getCoordinates(d),c={},b={},k={},g={},m={}; +b=this.element;this.droppables=$$(this.options.droppables);this.setContainer(this.options.container);if(this.options.style){if(this.options.modifiers.x=="left"&&this.options.modifiers.y=="top"){var c=b.getOffsetParent(),d=b.getStyles("left","top"); +if(c&&(d.left=="auto"||d.top=="auto")){b.setPosition(b.getPosition(c));}}if(b.getStyle("position")=="static"){b.setStyle("position","absolute");}}this.addEvent("start",this.checkDroppables,true); +this.overed=null;},setContainer:function(a){this.container=document.id(a);if(this.container&&typeOf(this.container)!="element"){this.container=document.id(this.container.getDocument().body); +}},start:function(a){if(this.container){this.options.limit=this.calculateLimit();}if(this.options.precalculate){this.positions=this.droppables.map(function(b){return b.getCoordinates(); +});}this.parent(a);},calculateLimit:function(){var j=this.element,e=this.container,d=document.id(j.getOffsetParent())||document.body,h=e.getCoordinates(d),c={},b={},k={},g={},m={}; ["top","right","bottom","left"].each(function(q){c[q]=j.getStyle("margin-"+q).toInt();b[q]=j.getStyle("border-"+q).toInt();k[q]=e.getStyle("margin-"+q).toInt(); g[q]=e.getStyle("border-"+q).toInt();m[q]=d.getStyle("padding-"+q).toInt();},this);var f=j.offsetWidth+c.left+c.right,p=j.offsetHeight+c.top+c.bottom,i=0,l=0,o=h.right-g.right-f,a=h.bottom-g.bottom-p; if(this.options.includeMargins){i+=c.left;l+=c.top;}else{o+=c.right;a+=c.bottom;}if(j.getStyle("position")=="relative"){var n=j.getCoordinates(d);n.left-=j.getStyle("left").toInt(); n.top-=j.getStyle("top").toInt();i-=n.left;l-=n.top;if(e.getStyle("position")!="relative"){i+=g.left;l+=g.top;}o+=c.left-n.left;a+=c.top-n.top;if(e!=d){i+=k.left+m.left; -l+=((Browser.ie6||Browser.ie7)?0:k.top)+m.top;}}else{i-=c.left;l-=c.top;if(e!=d){i+=h.left+g.left;l+=h.top+g.top;}}return{x:[i,o],y:[l,a]};},getDroppableCoordinates:function(c){var b=c.getCoordinates(); -if(c.getStyle("position")=="fixed"){var a=window.getScroll();b.left+=a.x;b.right+=a.x;b.top+=a.y;b.bottom+=a.y;}return b;},checkDroppables:function(){var a=this.droppables.filter(function(d,c){d=this.positions?this.positions[c]:this.getDroppableCoordinates(d); +if(!m.left&&i<0){i=0;}l+=d==document.body?0:k.top+m.top;if(!m.top&&l<0){l=0;}}}else{i-=c.left;l-=c.top;if(e!=d){i+=h.left+g.left;l+=h.top+g.top;}}return{x:[i,o],y:[l,a]}; +},getDroppableCoordinates:function(c){var b=c.getCoordinates();if(c.getStyle("position")=="fixed"){var a=window.getScroll();b.left+=a.x;b.right+=a.x;b.top+=a.y; +b.bottom+=a.y;}return b;},checkDroppables:function(){var a=this.droppables.filter(function(d,c){d=this.positions?this.positions[c]:this.getDroppableCoordinates(d); var b=this.mouse.now;return(b.x>d.left&&b.x<d.right&&b.y<d.bottom&&b.y>d.top);},this).getLast();if(this.overed!=a){if(this.overed){this.fireEvent("leave",[this.element,this.overed]); }if(a){this.fireEvent("enter",[this.element,a]);}this.overed=a;}},drag:function(a){this.parent(a);if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables(); }},stop:function(a){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,a]);this.overed=null;return this.parent(a);}});Element.implement({makeDraggable:function(a){var b=new Drag.Move(this,a); -this.store("dragger",b);return b;}});var Sortables=new Class({Implements:[Events,Options],options:{opacity:1,clone:false,revert:false,handle:false,dragOptions:{}},initialize:function(a,b){this.setOptions(b); +this.store("dragger",b);return b;}});var Sortables=new Class({Implements:[Events,Options],options:{opacity:1,clone:false,revert:false,handle:false,dragOptions:{},unDraggableTags:["button","input","a","textarea","select","option"]},initialize:function(a,b){this.setOptions(b); this.elements=[];this.lists=[];this.idle=true;this.addLists($$(document.id(a)||a));if(!this.options.clone){this.options.revert=false;}if(this.options.revert){this.effect=new Fx.Morph(null,Object.merge({duration:250,link:"cancel"},this.options.revert)); }},attach:function(){this.addLists(this.lists);return this;},detach:function(){this.lists=this.removeLists(this.lists);return this;},addItems:function(){Array.flatten(arguments).each(function(a){this.elements.push(a); var b=a.retrieve("sortables:start",function(c){this.start.call(this,c,a);}.bind(this));(this.options.handle?a.getElement(this.options.handle)||a:a).addEvent("mousedown",b); },this);return this;},addLists:function(){Array.flatten(arguments).each(function(a){this.lists.include(a);this.addItems(a.getChildren());},this);return this; },removeItems:function(){return $$(Array.flatten(arguments).map(function(a){this.elements.erase(a);var b=a.retrieve("sortables:start");(this.options.handle?a.getElement(this.options.handle)||a:a).removeEvent("mousedown",b); return a;},this));},removeLists:function(){return $$(Array.flatten(arguments).map(function(a){this.lists.erase(a);this.removeItems(a.getChildren());return a; -},this));},getClone:function(b,a){if(!this.options.clone){return new Element(a.tagName).inject(document.body);}if(typeOf(this.options.clone)=="function"){return this.options.clone.call(this,b,a,this.list); -}var c=a.clone(true).setStyles({margin:0,position:"absolute",visibility:"hidden",width:a.getStyle("width")}).addEvent("mousedown",function(d){a.fireEvent("mousedown",d); +},this));},getDroppableCoordinates:function(c){var d=c.getOffsetParent();var b=c.getPosition(d);var a={w:window.getScroll(),offsetParent:d.getScroll()}; +b.x+=a.offsetParent.x;b.y+=a.offsetParent.y;if(d.getStyle("position")=="fixed"){b.x-=a.w.x;b.y-=a.w.y;}return b;},getClone:function(b,a){if(!this.options.clone){return new Element(a.tagName).inject(document.body); +}if(typeOf(this.options.clone)=="function"){return this.options.clone.call(this,b,a,this.list);}var c=a.clone(true).setStyles({margin:0,position:"absolute",visibility:"hidden",width:a.getStyle("width")}).addEvent("mousedown",function(d){a.fireEvent("mousedown",d); });if(c.get("html").test("radio")){c.getElements("input[type=radio]").each(function(d,e){d.set("name","clone_"+e);if(d.get("checked")){a.getElements("input[type=radio]")[e].set("checked",true); -}});}return c.inject(this.list).setPosition(a.getPosition(a.getOffsetParent()));},getDroppables:function(){var a=this.list.getChildren().erase(this.clone).erase(this.element); +}});}return c.inject(this.list).setPosition(this.getDroppableCoordinates(this.element));},getDroppables:function(){var a=this.list.getChildren().erase(this.clone).erase(this.element); if(!this.options.constrain){a.append(this.lists).erase(this.list);}return a;},insert:function(c,b){var a="inside";if(this.lists.contains(b)){this.list=b; this.drag.droppables=this.getDroppables();}else{a=this.element.getAllPrevious().contains(b)?"before":"after";}this.element.inject(b,a);this.fireEvent("sort",[this.element,this.clone]); -},start:function(b,a){if(!this.idle||b.rightClick||["button","input","a","textarea"].contains(b.target.get("tag"))){return;}this.idle=false;this.element=a; -this.opacity=a.getStyle("opacity");this.list=a.getParent();this.clone=this.getClone(b,a);this.drag=new Drag.Move(this.clone,Object.merge({droppables:this.getDroppables()},this.options.dragOptions)).addEvents({onSnap:function(){b.stop(); +},start:function(b,a){if(!this.idle||b.rightClick||(!this.options.handle&&this.options.unDraggableTags.contains(b.target.get("tag")))){return;}this.idle=false; +this.element=a;this.opacity=a.getStyle("opacity");this.list=a.getParent();this.clone=this.getClone(b,a);this.drag=new Drag.Move(this.clone,Object.merge({droppables:this.getDroppables()},this.options.dragOptions)).addEvents({onSnap:function(){b.stop(); this.clone.setStyle("visibility","visible");this.element.setStyle("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone]); }.bind(this),onEnter:this.insert.bind(this),onCancel:this.end.bind(this),onComplete:this.end.bind(this)});this.clone.inject(this.element,"before");this.drag.start(b); -},end:function(){this.drag.detach();this.element.setStyle("opacity",this.opacity);if(this.effect){var b=this.element.getStyles("width","height"),d=this.clone,c=d.computePosition(this.element.getPosition(this.clone.getOffsetParent())); -var a=function(){this.removeEvent("cancel",a);d.destroy();};this.effect.element=d;this.effect.start({top:c.top,left:c.left,width:b.width,height:b.height,opacity:0.25}).addEvent("cancel",a).chain(a); -}else{this.clone.destroy();}this.reset();},reset:function(){this.idle=true;this.fireEvent("complete",this.element);},serialize:function(){var c=Array.link(arguments,{modifier:Type.isFunction,index:function(d){return d!=null; +},end:function(){this.drag.detach();this.element.setStyle("opacity",this.opacity);var a=this;if(this.effect){var c=this.element.getStyles("width","height"),e=this.clone,d=e.computePosition(this.getDroppableCoordinates(e)); +var b=function(){this.removeEvent("cancel",b);e.destroy();a.reset();};this.effect.element=e;this.effect.start({top:d.top,left:d.left,width:c.width,height:c.height,opacity:0.25}).addEvent("cancel",b).chain(b); +}else{this.clone.destroy();a.reset();}},reset:function(){this.idle=true;this.fireEvent("complete",this.element);},serialize:function(){var c=Array.link(arguments,{modifier:Type.isFunction,index:function(d){return d!=null; }});var b=this.lists.map(function(d){return d.getChildren().map(c.modifier||function(e){return e.get("id");},this);},this);var a=c.index;if(this.lists.length==1){a=0; }return(a||a===0)&&a>=0&&a<this.lists.length?b[a]:b;}});Request.implement({options:{initialDelay:5000,delay:5000,limit:60000},startTimer:function(b){var a=function(){if(!this.running){this.send({data:b}); }};this.lastDelay=this.options.initialDelay;this.timer=a.delay(this.lastDelay,this);this.completeCheck=function(c){clearTimeout(this.timer);this.lastDelay=(c)?this.options.delay:(this.lastDelay+this.options.delay).min(this.options.limit); diff --git a/module/web/media/js/purr_static.js b/module/webui/themes/dark/js/static/purr.js index 7e0aee949..9cbc503d9 100644 --- a/module/web/media/js/purr_static.js +++ b/module/webui/themes/dark/js/static/purr.js @@ -57,8 +57,9 @@ var Purr = new Class({ 'fx': { 'duration': 500 }, + 'highlight': false, 'highlightRepeat': false, - 'highlight': { // false to disable highlighting + 'highlight': { 'start': '#FF0', 'end': false } @@ -161,15 +162,15 @@ var Purr = new Class({ var buttonWrapper = new Element(this.options.elements.buttonWrapper, this.options.elementOptions.buttonWrapper); alert.grab(buttonWrapper); options.buttons.each(function(button){ - if(button.text !== undefined) + if(button.text != undefined) { var callbackButton = new Element(this.options.elements.button, this.options.elementOptions.button); callbackButton.set('html', button.text); - if(button.callback !== undefined) + if(button.callback != undefined) { callbackButton.addEvent('click', button.callback.pass(alert)); } - if(button.dismiss !== undefined && button.dismiss) + if(button.dismiss != undefined && button.dismiss) { callbackButton.addEvent('click', this.dismiss.pass(alert, this)); } @@ -177,7 +178,7 @@ var Purr = new Class({ } }, this); } - if(options.className !== undefined) + if(options.className != undefined) { alert.addClass(options.className); } @@ -233,7 +234,7 @@ var Purr = new Class({ 'opacity': 0 }); alertFx.start({ - 'opacity': [this.options.elementOptions.alert.styles.opacity, '.9'].pick() + 'opacity': [this.options.elementOptions.alert.styles.opacity, .9].pick(), }); }, @@ -253,7 +254,7 @@ var Purr = new Class({ 'fadeOut': function(alert){ if(this.holdUp) { - this.dismiss.delay(100, this, [alert, true]); + this.dismiss.delay(100, this, [alert, true]) return null; } var alertFx = alert.retrieve('fx'); @@ -263,7 +264,7 @@ var Purr = new Class({ } var to = { 'opacity': 0 - }; + } if(this.options.mode == 'top') { to['margin-top'] = '-'+alert.offsetHeight+'px'; @@ -288,7 +289,7 @@ Element.implement({ options = options || { 'mode':'top' }; - alert = new Purr(options); + alert = new Purr(options) this.store('alert', alert); } diff --git a/module/webui/themes/dark/js/static/purr.min.js b/module/webui/themes/dark/js/static/purr.min.js new file mode 100644 index 000000000..bf70e357d --- /dev/null +++ b/module/webui/themes/dark/js/static/purr.min.js @@ -0,0 +1 @@ +var Purr=new Class({options:{mode:"top",position:"left",elementAlertClass:"purr-element-alert",elements:{wrapper:"div",alert:"div",buttonWrapper:"div",button:"button"},elementOptions:{wrapper:{styles:{position:"fixed","z-index":"9999"},"class":"purr-wrapper"},alert:{"class":"purr-alert",styles:{opacity:".85"}},buttonWrapper:{"class":"purr-button-wrapper"},button:{"class":"purr-button"}},alert:{buttons:[],clickDismiss:!0,hoverWait:!0,hideAfter:5e3,fx:{duration:500},highlight:!1,highlightRepeat:!1,highlight:{start:"#FF0",end:!1}}},Implements:[Options,Events,Chain],initialize:function(t){return this.setOptions(t),this.createWrapper(),this},bindAlert:function(){return this.alert.bind(this)},createWrapper:function(){this.wrapper=new Element(this.options.elements.wrapper,this.options.elementOptions.wrapper),"top"==this.options.mode?this.wrapper.setStyle("top",0):this.wrapper.setStyle("bottom",0),document.id(document.body).grab(this.wrapper),this.positionWrapper(this.options.position)},positionWrapper:function(t){if("object"==typeOf(t)){var e=this.getWrapperCoords();this.wrapper.setStyles({bottom:"",left:t.x,top:t.y-e.height,position:"absolute"})}else"left"==t?this.wrapper.setStyle("left",0):"right"==t?this.wrapper.setStyle("right",0):this.wrapper.setStyle("left",window.innerWidth/2-this.getWrapperCoords().width/2);return this},getWrapperCoords:function(){this.wrapper.setStyle("visibility","hidden");var t=this.alert("need something in here to measure"),e=this.wrapper.getCoordinates();return t.destroy(),this.wrapper.setStyle("visibility",""),e},alert:function(t,e){e=Object.merge({},this.options.alert,e||{});var i=new Element(this.options.elements.alert,this.options.elementOptions.alert);if("string"==typeOf(t))i.set("html",t);else if("element"==typeOf(t))i.grab(t);else if("array"==typeOf(t)){var s=[];return t.each(function(t){s.push(this.alert(t,e))},this),s}if(i.store("options",e),e.buttons.length>0){e.clickDismiss=!1,e.hideAfter=!1,e.hoverWait=!1;var r=new Element(this.options.elements.buttonWrapper,this.options.elementOptions.buttonWrapper);i.grab(r),e.buttons.each(function(t){if(void 0!=t.text){var e=new Element(this.options.elements.button,this.options.elementOptions.button);e.set("html",t.text),void 0!=t.callback&&e.addEvent("click",t.callback.pass(i)),void 0!=t.dismiss&&t.dismiss&&e.addEvent("click",this.dismiss.pass(i,this)),r.grab(e)}},this)}void 0!=e.className&&i.addClass(e.className),this.wrapper.grab(i,"top"==this.options.mode?"bottom":"top");var o=Object.merge(this.options.alert.fx,e.fx),n=new Fx.Morph(i,o);return i.store("fx",n),this.fadeIn(i),e.highlight&&n.addEvent("complete",function(){i.highlight(e.highlight.start,e.highlight.end),e.highlightRepeat&&i.highlight.periodical(e.highlightRepeat,i,[e.highlight.start,e.highlight.end])}),e.hideAfter&&this.dismiss(i),e.clickDismiss&&i.addEvent("click",function(){this.holdUp=!1,this.dismiss(i,!0)}.bind(this)),e.hoverWait&&i.addEvents({mouseenter:function(){this.holdUp=!0}.bind(this),mouseleave:function(){this.holdUp=!1}.bind(this)}),i},fadeIn:function(t){var e=t.retrieve("fx");e.set({opacity:0}),e.start({opacity:[this.options.elementOptions.alert.styles.opacity,.9].pick()})},dismiss:function(t,e){e=e||!1;var i=t.retrieve("options");e?this.fadeOut(t):this.fadeOut.delay(i.hideAfter,this,t)},fadeOut:function(t){if(this.holdUp)return this.dismiss.delay(100,this,[t,!0]),null;var e=t.retrieve("fx");if(!e)return null;var i={opacity:0};"top"==this.options.mode?i["margin-top"]="-"+t.offsetHeight+"px":i["margin-bottom"]="-"+t.offsetHeight+"px",e.start(i),e.addEvent("complete",function(){t.destroy()})}});Element.implement({alert:function(t,e){var i=this.retrieve("alert");i||(e=e||{mode:"top"},i=new Purr(e),this.store("alert",i));var s=this.getCoordinates();i.alert(t,e),i.wrapper.setStyles({bottom:"",left:s.left-i.wrapper.getWidth()/2+this.getWidth()/2,top:s.top-i.wrapper.getHeight(),position:"absolute"})}});
\ No newline at end of file diff --git a/module/web/media/js/tinytab_static.js b/module/webui/themes/dark/js/static/tinytab.js index 6c38292f5..de50279fc 100644 --- a/module/web/media/js/tinytab_static.js +++ b/module/webui/themes/dark/js/static/tinytab.js @@ -20,11 +20,6 @@ provides: TinyTab initialize: function(tabs, contents, opt) { this.tabs = tabs; this.contents = contents; - this.header = $("tabsback"); - this.headers = []; - for(var i =0; i < this.tabs.length; i++){ - this.headers.push(""); - } if(!opt) opt = {}; this.css = opt.selectedClass || 'selected'; this.select(this.tabs[0]); @@ -40,9 +35,7 @@ provides: TinyTab this.tabs.removeClass(this.css); el.addClass(this.css); this.contents.setStyle('display','none'); - var index = this.tabs.indexOf(el); - this.header.set("text", this.headers[index]); - var content = this.contents[index]; + var content = this.contents[this.tabs.indexOf(el)]; content.setStyle('display','block'); this.fireEvent('change',[content,el]); } diff --git a/module/webui/themes/dark/js/static/tinytab.min.js b/module/webui/themes/dark/js/static/tinytab.min.js new file mode 100644 index 000000000..2f4fa0436 --- /dev/null +++ b/module/webui/themes/dark/js/static/tinytab.min.js @@ -0,0 +1 @@ +!function(){this.TinyTab=new Class({Implements:Events,initialize:function(s,t,e){this.tabs=s,this.contents=t,e||(e={}),this.css=e.selectedClass||"selected",this.select(this.tabs[0]),s.each(function(s){s.addEvent("click",function(t){this.select(s),t.stop()}.bind(this))}.bind(this))},select:function(s){this.tabs.removeClass(this.css),s.addClass(this.css),this.contents.setStyle("display","none");var t=this.contents[this.tabs.indexOf(s)];t.setStyle("display","block"),this.fireEvent("change",[t,s])}})}(document.id);
\ No newline at end of file diff --git a/module/web/templates/default/admin.html b/module/webui/themes/dark/tml/admin.html index b049411fd..42118eda4 100644 --- a/module/web/templates/default/admin.html +++ b/module/webui/themes/dark/tml/admin.html @@ -1,7 +1,7 @@ -{% extends 'default/base.html' %} +{% extends '/dark/tml/base.html' %} {% block head %} - <script type="text/javascript" src="media/js/admin.js"></script> + <script type="text/javascript" src="/dark/js/render/admin.min.js"></script> {% endblock %} @@ -9,13 +9,13 @@ {% block subtitle %}{{ _("Administrate") }}{% endblock %} {% block content %} - + <a href="#" id="quit-pyload" style="font-size: large; font-weight: bold;">{{_("Quit pyLoad")}}</a> | <a href="#" id="restart-pyload" style="font-size: large; font-weight: bold;">{{_("Restart pyLoad")}}</a> <br> <br> - {{ _("To add user or change passwords use:") }} <b>python pyLoadCore.py -u</b><br> + {{ _("To add user or change passwords use:") }} <b>python pyload.py -u</b><br> {{ _("Important: Admin user have always all permissions!") }} <form action="" method="POST"> diff --git a/module/webui/themes/dark/tml/base.html b/module/webui/themes/dark/tml/base.html new file mode 100644 index 000000000..e7179acfa --- /dev/null +++ b/module/webui/themes/dark/tml/base.html @@ -0,0 +1,177 @@ +<?xml version="1.0" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<link rel="stylesheet" type="text/css" href="/dark/css/dark.min.css"/> +<link rel="stylesheet" type="text/css" href="/dark/css/window.min.css"/> +<link rel="stylesheet" type="text/css" href="/dark/css/MooDialog.min.css"/> + +<script type="text/javascript" src="/dark/js/static/mootools-core.min.js"></script> +<script type="text/javascript" src="/dark/js/static/mootools-more.min.js"></script> +<script type="text/javascript" src="/dark/js/static/MooDialog.min.js"></script> +<script type="text/javascript" src="/dark/js/static/purr.min.js"></script> + + +<script type="text/javascript" src="/dark/js/render/base.min.js"></script> + +<title>{% block title %}pyLoad {{_("Webinterface")}}{% endblock %}</title> + +{% block head %} +{% endblock %} +</head> +<body> +<a class="anchor" name="top" id="top"></a> + +<div id="head-panel"> + + + <div id="head-search-and-login"> + {% block headpanel %} + + {% if user.is_authenticated %} + + +{% if update %} +<span> +<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("pyLoad Update available!")}}</span> +</span> +{% endif %} + + +{% if plugins %} +<span> +<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("Plugins updated, please restart!")}}</span> +</span> +{% endif %} + +<span id="cap_info" style="display: {% if captcha %}inline{%else%}none{% endif %}"> +<img src="/dark/img/default/images.png" alt="Captcha:" style="vertical-align:middle; margin:2px" /> +<span style="font-weight: bold; cursor: pointer; margin-right: 2px;">{{_("Captcha waiting")}}</span> +</span> + + <img src="/dark/img/default/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user.name}}</span> + <ul id="user-actions"> + <li><a href="/logout" class="action logout" rel="nofollow">{{_("Logout")}}</a></li> + {% if user.is_admin %} + <li><a href="/admin" class="action profile" rel="nofollow">{{_("Administrate")}}</a></li> + {% endif %} + <li><a href="/info" class="action info" rel="nofollow">{{_("Info")}}</a></li> + + </ul> +{% else %} + <span style="padding-right: 2px;">{{_("Please Login!")}}</span> +{% endif %} + + {% endblock %} + </div> + + <a href="/"><img id="head-logo" src="/dark/img/pyload-logo.png" alt="pyLoad" /></a> +{% if user.is_authenticated %} + <div id="head-menu"> + <ul> + + {% macro selected(name, right=False) -%} + {% if name in url -%}class="{% if right -%}right {% endif %}selected"{%- endif %} + {% if not name in url and right -%}class="right"{%- endif %} + {%- endmacro %} + + + {% block menu %} + <li> + <a href="/" title=""><img src="/dark/img/default/head-menu-home.png" alt="" /> {{_("Home")}}</a> + </li> + <li {{ selected('queue') }}> + <a href="/queue/" title=""><img src="/dark/img/default/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> + </li> + <li {{ selected('collector') }}> + <a href="/collector/" title=""><img src="/dark/img/default/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> + </li> + <li {{ selected('downloads') }}> + <a href="/downloads/" title=""><img src="/dark/img/default/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> + </li> + <li {{ selected('logs', True) }}> + <a href="/logs/" title=""><img src="/dark/img/default/head-menu-index.png" alt="" />{{_("Logs")}}</a> + </li> + <li {{ selected('settings', True) }}> + <a href="/settings/" title=""><img src="/dark/img/default/head-menu-config.png" alt="" />{{_("Config")}}</a> + </li> + {% endblock %} + + </ul> + </div>{% endif %} + + <div style="clear:both;"></div> +</div> + +{% if perms.STATUS %} +<ul id="page-actions2"> + <li id="action_play"><a href="#" class="action play" accesskey="o" rel="nofollow">{{_("Start")}}</a></li> + <li id="action_stop"><a href="#" class="action stop" accesskey="o" rel="nofollow">{{_("Stop")}}</a></li> + <li id="action_cancel"><a href="#" class="action cancel" accesskey="o" rel="nofollow">{{_("Cancel")}}</a></li> + <li id="action_add"><a href="#" class="action add" accesskey="o" rel="nofollow" >{{_("Add")}}</a></li> +</ul> +{% endif %} + +{% if perms.LIST %} +<ul id="page-actions"> + <li><span class="time">{{_("Download:")}}</span><a id="time" style=" background-color: {% if status.download %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm;color:black; "> {% if status.download %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li> + <li><span class="reconnect">{{_("Reconnect:")}}</span><a id="reconnect" style=" background-color: {% if status.reconnect %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm;color:black; "> {% if status.reconnect %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li> + <li><a class="action backlink">{{_("Speed:")}} <b id="speed">{{ status.speed }}</b></a></li> + <li><a class="action cog">{{_("Active:")}} <b id="aktiv" title="{{_("Active")}}">{{ status.active }}</b> / <b id="aktiv_from" title="{{_("Queued")}}">{{ status.queue }}</b> / <b id="aktiv_total" title="{{_("Total")}}">{{ status.total }}</b></a></li> + <li><a href="" class="action revisions" accesskey="o" rel="nofollow">{{_("Reload page")}}</a></li> +</ul> +{% endif %} + +{% block pageactions %} +{% endblock %} +<br/> + +<div id="body-wrapper" class="dokuwiki"> + +<div id="content" lang="en" dir="ltr"> + +<h1>{% block subtitle %}pyLoad - {{_("Webinterface")}}{% endblock %}</h1> + +{% block statusbar %} +{% endblock %} + + +<br/> + +<div class="level1" style="clear:both"> +</div> +<noscript><h1>Enable JavaScript to use the webinterface.</h1></noscript> + +{% for message in messages %} + <b><p>{{message}}</p></b> +{% endfor %} + +<div id="load-indicator" style="opacity: 0; float: right; margin-top: -10px;"> + <img src="/dark/img/default/ajax-loader.gif" alt="" style="padding-right: 5px"/> + {{_("loading")}} +</div> + +{% block content %} +{% endblock content %} + + <hr style="clear: both;" /> + +<div id="foot">© 2008-2014 pyLoad Team +<a href="#top" class="action top" accesskey="x"><span>{{_("Back to top")}}</span></a><br /> +<!--<div class="breadcrumbs"></div>--> + +</div> +</div> +</div> + +<div id="window_popup" style="display: none;"> + {% include '/dark/tml/window.html' %} + {% include '/dark/tml/captcha.html' %} + {% block hidden %} + {% endblock %} +</div> +</body> +</html> diff --git a/module/webui/themes/dark/tml/captcha.html b/module/webui/themes/dark/tml/captcha.html new file mode 100644 index 000000000..ae1afe444 --- /dev/null +++ b/module/webui/themes/dark/tml/captcha.html @@ -0,0 +1,42 @@ +<!-- Captcha box --> +<div id="cap_box" class="window_box"> + + <form id="cap_form" action="/json/set_captcha" method="POST" enctype="multipart/form-data" onsubmit="return false;"> + + <h1>{{_("Captcha reading")}}</h1> + <p id="cap_title">{{_("Please read the text on the captcha.")}}</p> + + <div id="cap_textual"> + + <input id="cap_id" name="cap_id" type="hidden" value="" /> + + <label>{{_("Captcha")}} + <span class="small">{{_("The captcha.")}}</span> + </label> + <span class="cont"> + <img id="cap_textual_img" src=""> + </span> + + <label>{{_("Text")}} + <span class="small">{{_("Input the text on the captcha.")}}</span> + </label> + <input id="cap_result" name="cap_result" type="text" size="20" /> + + </div> + + <div id="cap_positional" style="text-align: center"> + <img id="cap_positional_img" src="" style="margin: 10px; cursor:pointer"> + </div> + + <div id="button_bar" style="text-align: center"> + <span> + <button id="cap_submit" type="submit" style="margin-left: 0">{{_("Submit")}}</button> + <button id="cap_reset" type="reset" style="margin-left: 0">{{_("Close")}}</button> + </span> + </div> + + <div class="spacer"></div> + + </form> + +</div>
\ No newline at end of file diff --git a/module/web/templates/default/downloads.html b/module/webui/themes/dark/tml/downloads.html index 450b8a102..0c7fb9209 100644 --- a/module/web/templates/default/downloads.html +++ b/module/webui/themes/dark/tml/downloads.html @@ -1,4 +1,4 @@ -{% extends 'default/base.html' %} +{% extends '/dark/tml/base.html' %} {% block title %}Downloads - {{super()}} {% endblock %} @@ -19,7 +19,7 @@ </ul> </li> {% endfor %} - + {% for file in files.files %} <li> <a href='get/{{ file|escape }}'>{{ file }}</a></li> {% endfor %} diff --git a/module/webui/themes/dark/tml/folder.html b/module/webui/themes/dark/tml/folder.html new file mode 100644 index 000000000..05176d51e --- /dev/null +++ b/module/webui/themes/dark/tml/folder.html @@ -0,0 +1,15 @@ +<li class="folder"> + <input type="hidden" name="path" class="path" value="{{ path }}" /> + <input type="hidden" name="name" class="name" value="{{ name }}" /> + <span> + <b>{{ name }}</b> + <span class="buttons" style="opacity:0"> + <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/dark/img/default/pencil.png" /> + + <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/dark/img/default/delete.png" /> + + <img title="{{_("Add subdirectory")}}" class="mkdir" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/dark/img/default/add_folder.png" /> + </span> + </span> + <div style="display:none">{{ _("Folder is empty") }}</div> +</li>
\ No newline at end of file diff --git a/module/webui/themes/dark/tml/home.html b/module/webui/themes/dark/tml/home.html new file mode 100644 index 000000000..b350b705e --- /dev/null +++ b/module/webui/themes/dark/tml/home.html @@ -0,0 +1,263 @@ +{% extends '/dark/tml/base.html' %} +{% block head %} + +<script type="text/javascript"> + +var em; +var operafix = (navigator.userAgent.toLowerCase().search("opera") >= 0); + +document.addEvent("domready", function(){ + em = new EntryManager(); +}); + +var EntryManager = new Class({ + initialize: function(){ + this.json = new Request.JSON({ + url: "json/links", + secure: false, + async: true, + onSuccess: this.update.bind(this), + initialDelay: 0, + delay: 2500, + limit: 30000 + }); + + this.ids = [{% for link in content %} + {% if forloop.last %} + {{ link.id }} + {% else %} + {{ link.id }}, + {% endif %} + {% endfor %}]; + + this.entries = []; + this.container = $('LinksAktiv'); + + this.parseFromContent(); + + this.json.startTimer(); + }, + parseFromContent: function(){ + this.ids.each(function(id,index){ + var entry = new LinkEntry(id); + entry.parse(); + this.entries.push(entry) + }, this); + }, + update: function(data){ + + try{ + this.ids = this.entries.map(function(item){ + return item.fid + }); + + this.ids.filter(function(id){ + return !this.ids.contains(id) + },data).each(function(id){ + var index = this.ids.indexOf(id); + this.entries[index].remove(); + this.entries = this.entries.filter(function(item){return item.fid != this},id); + this.ids = this.ids.erase(id) + }, this); + + data.links.each(function(link, i){ + if (this.ids.contains(link.fid)){ + + var index = this.ids.indexOf(link.fid); + this.entries[index].update(link) + + }else{ + var entry = new LinkEntry(link.fid); + entry.insert(link); + this.entries.push(entry); + this.ids.push(link.fid); + this.container.adopt(entry.elements.tr,entry.elements.pgbTr); + entry.fade.start('opacity', 1); + entry.fadeBar.start('opacity', 1); + + } + }, this) + }catch(e){ + //alert(e) + } + } +}); + + +var LinkEntry = new Class({ + initialize: function(id){ + this.fid = id; + this.id = id; + }, + parse: function(){ + this.elements = { + tr: $("link_{id}".substitute({id: this.id})), + name: $("link_{id}_name".substitute({id: this.id})), + status: $("link_{id}_status".substitute({id: this.id})), + info: $("link_{id}_info".substitute({id: this.id})), + bleft: $("link_{id}_bleft".substitute({id: this.id})), + percent: $("link_{id}_percent".substitute({id: this.id})), + remove: $("link_{id}_remove".substitute({id: this.id})), + pgbTr: $("link_{id}_pgb_tr".substitute({id: this.id})), + pgb: $("link_{id}_pgb".substitute({id: this.id})) + }; + this.initEffects(); + }, + insert: function(item){ + try{ + + this.elements = { + tr: new Element('tr', { + 'html': '', + 'styles':{ + 'opacity': 0 + } + }), + name: new Element('td', { + 'html': item.name + }), + status: new Element('td', { + 'html': item.statusmsg + }), + info: new Element('td', { + 'html': item.info + }), + bleft: new Element('td', { + 'html': humanFileSize(item.size) + }), + percent: new Element('span', { + 'html': item.percent+ '% / '+ humanFileSize(item.size-item.bleft) + }), + remove: new Element('img',{ + 'src': '/dark/img/default/control_cancel.png', + 'styles':{ + 'vertical-align': 'middle', + 'margin-right': '-20px', + 'margin-left': '5px', + 'margin-top': '-2px', + 'cursor': 'pointer' + } + }), + pgbTr: new Element('tr', { + 'html':'' + }), + pgb: new Element('div', { + 'html': ' ', + 'styles':{ + 'height': '4px', + 'width': item.percent+'%', + 'background-color': '#ddd' + } + }) + }; + + this.elements.tr.adopt(this.elements.name,this.elements.status,this.elements.info,this.elements.bleft,new Element('td').adopt(this.elements.percent,this.elements.remove)); + this.elements.pgbTr.adopt(new Element('td',{'colspan':5}).adopt(this.elements.pgb)); + this.initEffects(); + }catch(e){ + alert(e) + } + }, + initEffects: function(){ + if(!operafix) + this.bar = new Fx.Morph(this.elements.pgb, {unit: '%', duration: 5000, link: 'link', fps:30}); + this.fade = new Fx.Tween(this.elements.tr); + this.fadeBar = new Fx.Tween(this.elements.pgbTr); + + this.elements.remove.addEvent('click', function(){ + new Request({method: 'get', url: '/json/abort_link/'+this.id}).send(); + }.bind(this)); + + }, + update: function(item){ + this.elements.name.set('text', item.name); + this.elements.status.set('text', item.statusmsg); + this.elements.info.set('text', item.info); + this.elements.bleft.set('text', item.format_size); + this.elements.percent.set('text', item.percent+ '% / '+ humanFileSize(item.size-item.bleft)); + if(!operafix) + { + this.bar.start({ + 'width': item.percent, + 'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex() + }); + } + else + { + this.elements.pgb.set( + 'styles', { + 'height': '4px', + 'width': item.percent+'%', + 'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex(), + }); + } + }, + remove: function(){ + this.fade.start('opacity',0).chain(function(){this.elements.tr.dispose();}.bind(this)); + this.fadeBar.start('opacity',0).chain(function(){this.elements.pgbTr.dispose();}.bind(this)); + + } + }); +</script> + +{% endblock %} + +{% block subtitle %} +{{_("Active Downloads")}} +{% endblock %} + +{% block menu %} +<li class="selected"> + <a href="/" title=""><img src="/dark/img/default/head-menu-home.png" alt="" /> {{_("Home")}}</a> +</li> +<li> + <a href="/queue/" title=""><img src="/dark/img/default/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> +</li> +<li> + <a href="/collector/" title=""><img src="/dark/img/default/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> +</li> +<li> + <a href="/downloads/" title=""><img src="/dark/img/default/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> +</li> +<li class="right"> + <a href="/logs/" title=""><img src="/dark/img/default/head-menu-index.png" alt="" />{{_("Logs")}}</a> +</li> +<li class="right"> + <a href="/settings/" title=""><img src="/dark/img/default/head-menu-config.png" alt="" />{{_("Config")}}</a> +</li> +{% endblock %} + +{% block content %} +<table width="100%" class="queue"> + <thead> + <tr class="header"> + <th>{{_("Name")}}</th> + <th>{{_("Status")}}</th> + <th>{{_("Information")}}</th> + <th>{{_("Size")}}</th> + <th>{{_("Progress")}}</th> + </tr> + </thead> + <tbody id="LinksAktiv"> + + {% for link in content %} + <tr id="link_{{ link.id }}"> + <td id="link_{{ link.id }}_name">{{ link.name }}</td> + <td id="link_{{ link.id }}_status">{{ link.status }}</td> + <td id="link_{{ link.id }}_info">{{ link.info }}</td> + <td id="link_{{ link.id }}_bleft">{{ link.format_size }}</td> + <td> + <span id="link_{{ link.id }}_percent">{{ link.percent }}% /{{ link.bleft }}</span> + <img id="link_{{ link.id }}_remove" style="vertical-align: middle; margin-right: -20px; margin-left: 5px; margin-top: -2px; cursor:pointer;" src="/dark/img/default/control_cancel.png"/> + </td> + </tr> + <tr id="link_{{ link.id }}_pgb_tr"> + <td colspan="5"> + <div id="link_{{ link.id }}_pgb" class="progressBar" style="background-color: green; height:4px; width: {{ link.percent }}%;"> </div> + </td> + </tr> + {% endfor %} + + </tbody> +</table> +{% endblock %}
\ No newline at end of file diff --git a/module/webui/themes/dark/tml/info.html b/module/webui/themes/dark/tml/info.html new file mode 100644 index 000000000..7ff2b639b --- /dev/null +++ b/module/webui/themes/dark/tml/info.html @@ -0,0 +1,76 @@ +{% extends '/dark/tml/base.html' %} + +{% block head %} +{% endblock %} + +{% block title %}{{ _("Information") }} - {{ super() }} {% endblock %} +{% block subtitle %}{{ _("Information") }}{% endblock %} + +{% block content %} + <h3>{{ _("News") }}</h3> + + <ul id="twitter_update_list"></ul> + <script type="text/javascript" src="http://twitter.com/javascripts/blogger.min.js"></script> + <script type="text/javascript" src="http://api.twitter.com/1/statuses/user_timeline.json?screen_name=pyLoad&include_rts=true&count=5&callback=twitterCallback2"></script> + + <h3>{{ _("Support") }}</h3> + + <ul> + <li style="font-weight:bold;"> + <a href="http://pyload.org/wiki" target="_blank">Wiki</a> + | + <a href="http://forum.pyload.org/" target="_blank">Forum</a> + | + <a href="http://pyload.org/irc/" target="_blank">Chat</a> + </li> + <li style="font-weight:bold;"><a href="http://docs.pyload.org" target="_blank">Documentation</a></li> + <li style="font-weight:bold;"><a href="https://bitbucket.org/spoob/pyload/overview" target="_blank">Development</a></li> + <li style="font-weight:bold;"><a href="https://bitbucket.org/spoob/pyload/issues?status=new&status=open" target="_blank">Issue Tracker</a></li> + + </ul> + + <h3>{{ _("System") }}</h3> + <table class="system"> + <tr> + <td>{{ _("Python:") }}</td> + <td>{{ python }}</td> + </tr> + <tr> + <td>{{ _("OS:") }}</td> + <td>{{ os }}</td> + </tr> + <tr> + <td>{{ _("pyLoad version:") }}</td> + <td>{{ version }}</td> + </tr> + <tr> + <td>{{ _("Installation Folder:") }}</td> + <td>{{ folder }}</td> + </tr> + <tr> + <td>{{ _("Config Folder:") }}</td> + <td>{{ config }}</td> + </tr> + <tr> + <td>{{ _("Download Folder:") }}</td> + <td>{{ download }}</td> + </tr> + <tr> + <td>{{ _("Free Space:") }}</td> + <td>{{ freespace }}</td> + </tr> + <tr> + <td>{{ _("Language:") }}</td> + <td>{{ language }}</td> + </tr> + <tr> + <td>{{ _("Webinterface Port:") }}</td> + <td>{{ webif }}</td> + </tr> + <tr> + <td>{{ _("Remote Interface Port:") }}</td> + <td>{{ remote }}</td> + </tr> + </table> + +{% endblock %}
\ No newline at end of file diff --git a/module/webui/themes/dark/tml/login.html b/module/webui/themes/dark/tml/login.html new file mode 100644 index 000000000..9f5e2cb2f --- /dev/null +++ b/module/webui/themes/dark/tml/login.html @@ -0,0 +1,37 @@ +{% extends '/dark/tml/base.html' %} + +{% block title %}{{_("Login")}} - {{super()}} {% endblock %} + +{% block content %} + +<div class="centeralign"> +<form action="" method="post" accept-charset="utf-8" id="login"> + <div class="no"> + <input type="hidden" name="do" value="login" /> + <fieldset> + <legend>Login</legend> +{% if errors %} +<p style="color:red;">{{_("Your username and password didn't match. Please try again.")}}</p> +{% endif %} + <table id="login_table"> + <tr> + <td>{{_("Username")}}</td> + <td><input type="text" size="20" name="username" /></td> + </tr> + <tr> + <td>{{_("Password")}}</td> + <td><input type="password" size="20" name="password" /></td> + </tr> +<tr> +<td> </td> + <td><input type="submit" value="Login" class="button" /></td> +</tr> +</table> + </fieldset> + </div> +</form> + +</div> +<br> + +{% endblock %} diff --git a/module/web/templates/default/logout.html b/module/webui/themes/dark/tml/logout.html index d3f07472b..5320e07f5 100644 --- a/module/web/templates/default/logout.html +++ b/module/webui/themes/dark/tml/logout.html @@ -1,4 +1,4 @@ -{% extends 'default/base.html' %} +{% extends '/dark/tml/base.html' %} {% block head %} <meta http-equiv="refresh" content="3; url=/"> diff --git a/module/web/templates/default/logs.html b/module/webui/themes/dark/tml/logs.html index d6288df0e..e178c6c5c 100644 --- a/module/web/templates/default/logs.html +++ b/module/webui/themes/dark/tml/logs.html @@ -1,9 +1,9 @@ -{% extends 'default/base.html' %} +{% extends '/dark/tml/base.html' %} {% block title %}{{_("Logs")}} - {{super()}} {% endblock %} {% block subtitle %}{{_("Logs")}}{% endblock %} {% block head %} -<link rel="stylesheet" type="text/css" href="/media/default/css/log.css"/> +<link rel="stylesheet" type="text/css" href="/dark/css/log.min.css"/> {% endblock %} {% block content %} diff --git a/module/web/templates/default/pathchooser.html b/module/webui/themes/dark/tml/pathchooser.html index d00637055..2b94f1019 100644 --- a/module/web/templates/default/pathchooser.html +++ b/module/webui/themes/dark/tml/pathchooser.html @@ -1,6 +1,6 @@ <html> <head> - <script class="javascript"> + <script class="javascript"> function chosen() { opener.ifield.value = document.forms[0].p.value; @@ -22,23 +22,23 @@ { document.forms[0].p.value = file; setValid(); - + } - </script> - <link rel="stylesheet" type="text/css" href="/media/default/css/pathchooser.css"/> + </script> + <link rel="stylesheet" type="text/css" href="/dark/css/pathchooser.min.css"/> </head> <body{% if type == 'file' %}{% if not oldfile %} onload="setInvalid();"{% endif %}{% endif %}> <center> <div id="paths"> - <form method="get" action="?" onSubmit="chosen();" onReset="exit();"> - <input type="text" name="p" value="{{ oldfile|default(cwd) }}" size="60" onfocus="setValid();"> - <input type="submit" value="Ok" name="send"> - </form> - + <form method="get" action="?" onSubmit="chosen();" onReset="exit();"> + <input type="text" name="p" value="{{ oldfile|default(cwd) }}" size="60" onfocus="setValid();"> + <input type="submit" value="Ok" name="send"> + </form> + {% if type == 'folder' %} - <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/pathchooser" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/pathchooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> + <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/pathchooser" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/pathchooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> {% else %} - <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/filechooser/" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/filechooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> + <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/filechooser/" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/filechooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> {% endif %} </div> <table border="0" cellspacing="0" cellpadding="3"> @@ -48,13 +48,13 @@ <th>{{_("type")}}</th> <th>{{_("last modified")}}</th> </tr> - {% if parentdir %} + {% if parentdir %} <tr> <td colspan="4"> <a href="{% if type == 'folder' %}{{ "/pathchooser/" + parentdir|quotepath }}{% else %}{{ "/filechooser/" + parentdir|quotepath }}{% endif %}"><span class="parentdir">{{_("parent directory")}}</span></a> </td> </tr> - {% endif %} + {% endif %} {% for file in files %} <tr> {% if type == 'folder' %} diff --git a/module/webui/themes/dark/tml/queue.html b/module/webui/themes/dark/tml/queue.html new file mode 100644 index 000000000..f68079106 --- /dev/null +++ b/module/webui/themes/dark/tml/queue.html @@ -0,0 +1,104 @@ +{% extends '/dark/tml/base.html' %} +{% block head %} + +<script type="text/javascript" src="/dark/js/render/package.min.js"></script> + +<script type="text/javascript"> + +document.addEvent("domready", function(){ + var pUI = new PackageUI("url", {{ target }}); +}); +</script> +{% endblock %} + +{% if target %} + {% set name = _("Queue") %} +{% else %} + {% set name = _("Collector") %} +{% endif %} + +{% block title %}{{name}} - {{super()}} {% endblock %} +{% block subtitle %}{{name}}{% endblock %} + +{% block pageactions %} +<ul id="page-actions-more"> + <li id="del_finished"><a style="padding: 0; font-weight: bold;" href="#">{{_("Delete Finished")}}</a></li> + <li id="restart_failed"><a style="padding: 0; font-weight: bold;" href="#">{{_("Restart Failed")}}</a></li> +</ul> +{% endblock %} + +{% block content %} +{% autoescape true %} + +<ul id="package-list" style="list-style: none; padding-left: 0; margin-top: -10px;"> +{% for package in content %} + <li> +<div id="package_{{package.pid}}" class="package"> + <div class="order" style="display: none;">{{ package.order }}</div> + + <div class="packagename" style="cursor: pointer"> + <img class="package_drag" src="/dark/img/default/folder.png" style="cursor: move; margin-bottom: -2px"> + <span class="name">{{package.name}}</span> + + <span class="buttons" style="opacity:0"> + <img title="{{_("Delete Package")}}" style="cursor: pointer" width="12px" height="12px" src="/dark/img/default/delete.png" /> + + <img title="{{_("Restart Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/dark/img/default/arrow_refresh.png" /> + + <img title="{{_("Edit Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/dark/img/default/pencil.png" /> + + <img title="{{_("Move Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/dark/img/default/package_go.png" /> + </span> + </div> + {% set progress = (package.linksdone * 100) / package.linkstotal %} + + <div id="progress" style="border-radius: 4px; border: 1px solid grey; width: 50%; height: 1em"> + <div style="width: {{ progress }}%; height: 100%; background-color: #525252;"></div> + <label style="font-size: 0.8em; font-weight: bold; padding-left: 5px; position: relative; top: -17px"> + {{ package.sizedone|formatsize }} / {{ package.sizetotal|formatsize }}</label> + <label style="font-size: 0.8em; font-weight: bold; padding-right: 5px ;float: right; position: relative; top: -17px"> + {{ package.linksdone }} / {{ package.linkstotal }}</label> + </div> + <div style="clear: both; margin-bottom: -10px"></div> + + <div id="children_{{package.pid}}" style="display: none;" class="children"> + <span class="child_secrow">{{_("Folder:")}} <span class="folder">{{package.folder}}</span> | {{_("Password:")}} <span class="password">{{package.password}}</span></span> + <ul id="sort_children_{{package.pid}}" style="list-style: none; padding-left: 0"> + </ul> + </div> +</div> + </li> +{% endfor %} +</ul> +{% endautoescape %} +{% endblock %} + +{% block hidden %} +<div id="pack_box" class="window_box" style="z-index: 2"> + <form id="pack_form" action="/json/edit_package" method="POST" enctype="multipart/form-data"> + <h1>{{_("Edit Package")}}</h1> + <p>{{_("Edit the package detais below.")}}</p> + <input name="pack_id" id="pack_id" type="hidden" value=""/> + <label for="pack_name">{{_("Name")}} + <span class="small">{{_("The name of the package.")}}</span> + </label> + <input id="pack_name" name="pack_name" type="text" size="20" /> + + <label for="pack_folder">{{_("Folder")}} + <span class="small">{{_("Name of subfolder for these downloads.")}}</span> + </label> + <input id="pack_folder" name="pack_folder" type="text" size="20" /> + + <label for="pack_pws">{{_("Password")}} + <span class="small">{{_("List of passwords used for unrar.")}}</span> + </label> + <textarea rows="3" name="pack_pws" id="pack_pws"></textarea> + + <button type="submit">{{_("Submit")}}</button> + <button id="pack_reset" style="margin-left: 0" type="reset" >{{_("Reset")}}</button> + <div class="spacer"></div> + + </form> + +</div> +{% endblock %}
\ No newline at end of file diff --git a/module/webui/themes/dark/tml/settings.html b/module/webui/themes/dark/tml/settings.html new file mode 100644 index 000000000..c9c0bed8a --- /dev/null +++ b/module/webui/themes/dark/tml/settings.html @@ -0,0 +1,204 @@ +{% extends '/dark/tml/base.html' %} + +{% block title %}{{ _("Config") }} - {{ super() }} {% endblock %} +{% block subtitle %}{{ _("Config") }}{% endblock %} + +{% block head %} + <script type="text/javascript" src="/dark/js/static/tinytab.min.js"></script> + <script type="text/javascript" src="/dark/js/static/MooDropMenu.min.js"></script> + <script type="text/javascript" src="/dark/js/render/settings.min.js"></script> + +{% endblock %} + +{% block content %} + + <ul id="toptabs" class="tabs"> + <li><a class="selected" href="#">{{ _("General") }}</a></li> + <li><a href="#">{{ _("Plugins") }}</a></li> + <li><a href="#">{{ _("Accounts") }}</a></li> + </ul> + + <div id="tabsback" style="height: 20px; padding-left: 150px; color: white; font-weight: bold;"> + + </div> + + <span id="tabs-body"> + <!-- General --> + <span id="general" class="active tabContent"> + <ul class="nav tabs"> + <li class> + <a>Menu</a> + <ul id="general-menu"> + {% for entry,name in conf.general %} + <nobr> + <li style="color:white;" id="general|{{ entry }}">{{ name }}</li> + </nobr> + <br> + {% endfor %} + </ul> + </li> + </ul> + + <form id="general_form" action="" method="POST" autocomplete="off"> + <span id="general_form_content"> + <br> + <h3> {{ _("Choose a section from the menu") }}</h3> + <br> + </span> + + <input id="general|submit" class="styled_button" type="submit" value="{{_("Submit")}}"/> + </form> + </span> + + <!-- Plugins --> + <span id="plugins" class="tabContent"> + <ul class="nav tabs"> + <li class> + <a>Menu</a> + <ul id="plugin-menu"> + {% for entry,name in conf.plugin %} + <nobr> + <li id="plugin|{{ entry }}">{{ name }}</li> + </nobr> + <br> + {% endfor %} + </ul> + </li> + </ul> + + + <form id="plugin_form" action="" method="POST" autocomplete="off"> + + <span id="plugin_form_content"> + <br> + <h3> {{ _("Choose a section from the menu") }}</h3> + <br> + </span> + <input id="plugin|submit" class="styled_button" type="submit" value="{{_("Submit")}}"/> + </form> + + </span> + + <!-- Accounts --> + <span id="accounts" class="tabContent"> + <form id="account_form" action="/json/update_accounts" method="POST"> + + <table class="settable wide"> + + <thead> + <tr> + <th>{{ _("Plugin") }}</th> + <th>{{ _("Name") }}</th> + <th>{{ _("Password") }}</th> + <th>{{ _("Status") }}</th> + <th>{{ _("Premium") }}</th> + <th>{{ _("Valid until") }}</th> + <th>{{ _("Traffic left") }}</th> + <th>{{ _("Time") }}</th> + <th>{{ _("Max Parallel") }}</th> + <th>{{ _("Delete?") }}</th> + </tr> + </thead> + + + {% for account in conf.accs %} + {% set plugin = account.type %} + <tr> + <td> + <span style="padding:5px">{{ plugin }}</span> + </td> + + <td><label for="{{plugin}}|password;{{account.login}}" + style="color:grey;">{{ account.login }}</label></td> + <td> + <input id="{{plugin}}|password;{{account.login}}" + name="{{plugin}}|password;{{account.login}}" + type="password" value="{{account.password}}" size="12"/> + </td> + <td> + {% if account.valid %} + <span style="font-weight: bold; color: #006400;"> + {{ _("valid") }} + {% else %} + <span style="font-weight: bold; color: #8b0000;"> + {{ _("not valid") }} + {% endif %} + </span> + </td> + <td> + {% if account.premium %} + <span style="font-weight: bold; color: #006400;"> + {{ _("yes") }} + {% else %} + <span style="font-weight: bold; color: #8b0000;"> + {{ _("no") }} + {% endif %} + </span> + </td> + <td> + <span style="font-weight: bold;"> + {{ account.validuntil }} + </span> + </td> + <td> + <span style="font-weight: bold;"> + {{ account.trafficleft }} + </span> + </td> + <td> + <input id="{{plugin}}|time;{{account.login}}" + name="{{plugin}}|time;{{account.login}}" type="text" + size="7" value="{{account.time}}"/> + </td> + <td> + <input id="{{plugin}}|limitdl;{{account.login}}" + name="{{plugin}}|limitdl;{{account.login}}" type="text" + size="2" value="{{account.limitdl}}"/> + </td> + <td> + <input id="{{plugin}}|delete;{{account.login}}" + name="{{plugin}}|delete;{{account.login}}" type="checkbox" + value="True"/> + </td> + </tr> + {% endfor %} + </table> + + <button id="account_submit" type="submit" class="styled_button">{{_("Submit")}}</button> + <button id="account_add" style="margin-left: 0" type="submit" class="styled_button">{{_("Add")}}</button> + </form> + </span> + </span> +{% endblock %} +{% block hidden %} +<div id="account_box" class="window_box" style="z-index: 2"> +<form id="add_account_form" action="/json/add_account" method="POST" enctype="multipart/form-data"> +<h1>{{_("Add Account")}}</h1> +<p>{{_("Enter your account data to use premium features.")}}</p> +<label for="account_login">{{_("Login")}} +<span class="small">{{_("Your username.")}}</span> +</label> +<input id="account_login" name="account_login" type="text" size="20" /> + +<label for="account_password">{{_("Password")}} +<span class="small">{{_("The password for this account.")}}</span> +</label> +<input id="account_password" name="account_password" type="password" size="20" /> + +<label for="account_type">{{_("Type")}} +<span class="small">{{_("Choose the hoster for your account.")}}</span> +</label> + <select name=account_type id="account_type"> + {% for type in types|sort %} + <option value="{{ type }}">{{ type }}</option> + {% endfor %} + </select> + +<button id="account_add_button" type="submit">{{_("Add")}}</button> +<button id="account_reset" style="margin-left: 0" type="reset">{{_("Reset")}}</button> +<div class="spacer"></div> + +</form> + +</div> +{% endblock %}
\ No newline at end of file diff --git a/module/webui/themes/dark/tml/settings_item.html b/module/webui/themes/dark/tml/settings_item.html new file mode 100644 index 000000000..e417e564c --- /dev/null +++ b/module/webui/themes/dark/tml/settings_item.html @@ -0,0 +1,48 @@ +<table class="settable"> + {% if section.outline %} + <tr><th colspan="2">{{ section.outline }}</th></tr> + {% endif %} + {% for okey, option in section.iteritems() %} + {% if okey not in ("desc","outline") %} + <tr> + <td><label for="{{skey}}|{{okey}}" + style="color:white;">{{ option.desc }}:</label></td> + <td> + {% if option.type == "bool" %} + <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> + <option {% if option.value %} selected="selected" + {% endif %}value="True">{{ _("on") }}</option> + <option {% if not option.value %} selected="selected" + {% endif %}value="False">{{ _("off") }}</option> + </select> + {% elif ";" in option.type %} + <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> + {% for entry in option.list %} + <option {% if option.value == entry %} + selected="selected" {% endif %}>{{ entry }}</option> + {% endfor %} + </select> + {% elif option.type == "folder" %} + <input name="{{skey}}|{{okey}}" type="text" + id="{{skey}}|{{okey}}" value="{{option.value}}"/> + <input name="browsebutton" type="button" + onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); pathchooser = window.open('{% if option.value %}{{ "/pathchooser/" + option.value|quotepath }}{% else %}{{ pathroot }}{% endif %}', 'pathchooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); pathchooser.ifield = ifield; window.ifield = ifield;" + value="{{_("Browse")}}"/> + {% elif option.type == "file" %} + <input name="{{skey}}|{{okey}}" type="text" + id="{{skey}}|{{okey}}" value="{{option.value}}"/> + <input name="browsebutton" type="button" + onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); filechooser = window.open('{% if option.value %}{{ "/filechooser/" + option.value|quotepath }}{% else %}{{ fileroot }}{% endif %}', 'filechooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); filechooser.ifield = ifield; window.ifield = ifield;" + value="{{_("Browse")}}"/> + {% elif option.type == "password" %} + <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" + type="password" value="{{option.value}}"/> + {% else %} + <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" + type="text" value="{{option.value}}"/> + {% endif %} + </td> + </tr> + {% endif %} + {% endfor %} +</table>
\ No newline at end of file diff --git a/module/webui/themes/dark/tml/window.html b/module/webui/themes/dark/tml/window.html new file mode 100644 index 000000000..0b4f5362b --- /dev/null +++ b/module/webui/themes/dark/tml/window.html @@ -0,0 +1,52 @@ +<iframe id="upload_target" name="upload_target" src="" style="display: none; width:0;height:0"></iframe> + +<div id="add_box" class="window_box"> +<form id="add_form" action="/json/add_package" method="POST" enctype="multipart/form-data"> +<h1>{{_("Add Package")}}</h1> +<p>{{_("Paste your links or upload a container.")}}</p> +<label for="add_name">{{_("Name")}} +<span class="small">{{_("The name of the new package.")}}</span> +</label> +<input id="add_name" name="add_name" type="text" size="20" /> + +<label for="add_links">{{_("Links")}} +<span class="small">{{_("Paste your links here or any text and press the filter button.")}}</span> +<span class="small"> {{ _("Filter urls") }} +<img alt="URIParsing" Title="Parse Uri" src="/dark/img/default/parseUri.png" style="cursor:pointer; vertical-align: text-bottom;" onclick="parseUri()"/> +</span> + +</label> +<textarea rows="5" name="add_links" id="add_links"></textarea> + +<label for="add_password">{{_("Password")}} + <span class="small">{{_("Password for RAR-Archive")}}</span> +</label> +<input id="add_password" name="add_password" type="text" size="20"> + +<label>{{_("File")}} +<span class="small">{{_("Upload a container.")}}</span> +</label> +<input type="file" name="add_file" id="add_file"/> + +<label for="add_dest">{{_("Destination")}} +</label> +<span class="cont"> +<table class="window_table"> +<tr> + <td>{{_("Queue")}}</td> + <td><input type="radio" name="add_dest" id="add_dest" value="1" checked="checked" /></td> +</tr> +<tr> + <td>{{_("Collector")}}</td> + <td><input type="radio" name="add_dest" id="add_dest2" value="0" /></td> +</tr> +</table> +</span> + +<button type="submit">{{_("Add Package")}}</button> +<button id="add_reset" style="margin-left:0;" type="reset">{{_("Reset")}}</button> +<div class="spacer"></div> + +</form> + +</div>
\ No newline at end of file diff --git a/module/web/media/default/css/MooDialog.css b/module/webui/themes/default/css/MooDialog.css index 48c9166ad..d26bf2ff2 100644 --- a/module/web/media/default/css/MooDialog.css +++ b/module/webui/themes/default/css/MooDialog.css @@ -44,7 +44,7 @@ } .MooDialog .close { - background: url(/media/img/dialog-close.png) no-repeat; + background: url(../img/MooDialog/dialog-close.png) no-repeat; width: 16px; height: 16px; display: block; @@ -76,17 +76,16 @@ .MooDialog .MooDialogConfirm, .MooDialog .MooDialogPrompt, .MooDialog .MooDialogError { - background: url(/media/img/dialog-warning.png) no-repeat; + background: url(../img/MooDialog/dialog-warning.png) no-repeat; padding-left: 40px; min-height: 40px; } .MooDialog .MooDialogConfirm, .MooDialog .MooDialogPromt { - background: url(/media/img/dialog-question.png) no-repeat; + background: url(../img/MooDialog/dialog-question.png) no-repeat; } .MooDialog .MooDialogError { - background: url(/media/img/dialog-error.png) no-repeat; + background: url(../img/MooDialog/dialog-error.png) no-repeat; } - diff --git a/module/webui/themes/default/css/default.css b/module/webui/themes/default/css/default.css new file mode 100644 index 000000000..5d4b9ebf2 --- /dev/null +++ b/module/webui/themes/default/css/default.css @@ -0,0 +1,902 @@ +.hidden { + display:none; +} +.leftalign { + text-align:left; +} +.centeralign { + text-align:center; +} +.rightalign { + text-align:right; +} + + +.dokuwiki div.plugin_translation ul li a.wikilink1:link, .dokuwiki div.plugin_translation ul li a.wikilink1:hover, .dokuwiki div.plugin_translation ul li a.wikilink1:active, .dokuwiki div.plugin_translation ul li a.wikilink1:visited { + background-color:#000080; + color:#fff !important; + text-decoration:none; + padding:0 0.2em; + margin:0.1em 0.2em; + border:none !important; +} +.dokuwiki div.plugin_translation ul li a.wikilink2:link, .dokuwiki div.plugin_translation ul li a.wikilink2:hover, .dokuwiki div.plugin_translation ul li a.wikilink2:active, .dokuwiki div.plugin_translation ul li a.wikilink2:visited { + background-color:#808080; + color:#fff !important; + text-decoration:none; + padding:0 0.2em; + margin:0.1em 0.2em; + border:none !important; +} + +.dokuwiki div.plugin_translation ul li a:hover img { + opacity:1.0; + height:15px; +} + +body { + margin:0; + padding:0; + background-color:white; + color:black; + font-size:12px; + font-family:Verdana, Helvetica, "Lucida Grande", Lucida, Arial, sans-serif; + font-family:sans-serif; + font-size:99, 96%; + font-size-adjust:none; + font-style:normal; + font-variant:normal; + font-weight:normal; + line-height:normal; +} +hr { + border-width:0; + border-bottom:1px #aaa dotted; +} +img { + border:none; +} +form { + margin:0px; + padding:0px; + border:none; + display:inline; + background:transparent; +} +ul li { + margin:5px; +} +textarea { + font-family:monospace; +} +table { + margin:0.5em 0; + border-collapse:collapse; +} +td { + padding:0.25em; + border:1pt solid #ADB9CC; +} +a { + color:#3465a4; + text-decoration:none; +} +a:hover { + text-decoration:underline; +} + +option { + border:0 none #fff; +} +strong.highlight { + background-color:#fc9; + padding:1pt; +} +#pagebottom { + clear:both; +} +hr { + height:1px; + color:#c0c0c0; + background-color:#c0c0c0; + border:none; + margin:.2em 0 .2em 0; +} + +.invisible { + margin:0px; + border:0px; + padding:0px; + height:0px; + visibility:hidden; +} +.left { + float:left !important; +} +.right { + float:right !important; +} +.center { + text-align:center; +} +div#body-wrapper { + padding:40px 40px 10px 40px; + font-size:127%; +} +div#content { + margin-top:-20px; + padding:0; + font-size:14px; + color:black; + line-height:1.5em; +} +h1, h2, h3, h4, h5, h6 { + background:transparent none repeat scroll 0 0; + border-bottom:1px solid #aaa; + color:black; + font-weight:normal; + margin:0; + padding:0; + padding-bottom:0.17em; + padding-top:0.5em; +} +h1 { + font-size:188%; + line-height:1.2em; + margin-bottom:0.1em; + padding-bottom:0; +} +h2 { + font-size:150%; +} +h3, h4, h5, h6 { + border-bottom:none; + font-weight:bold; +} +h3 { + font-size:132%; +} +h4 { + font-size:116%; +} +h5 { + font-size:100%; +} +h6 { + font-size:80%; +} +ul#page-actions, ul#page-actions-more { + float:right; + margin:10px 10px 0 10px; + padding:6px; + color:black; + background-color:#ececec; + list-style-type:none; + white-space: nowrap; + border-radius:5px; + -moz-border-radius:5px; +} +ul#user-actions { + padding:5px; + margin:0; + display:inline; + color:black; + background-color:#ececec; + list-style-type:none; + -moz-border-radius:3px; + border-radius:3px; +} +ul#page-actions li, ul#user-actions li, ul#page-actions-more li { + display:inline; +} +ul#page-actions a, ul#user-actions a, ul#page-actions-more a { + text-decoration:none; + color:black; + display:inline; + margin:0 3px; + padding:2px 0px 2px 18px; +} +ul#page-actions a:hover, ul#page-actions a:focus, ul#user-actions a:hover, ul#user-actions a:focus { + /*text-decoration:underline;*/ +} +/***************************/ +ul#page-actions2 { + float:left; + margin:10px 10px 0 10px; + padding:6px; + color:black; + background-color:#ececec; + list-style-type:none; + border-radius:5px; + -moz-border-radius:5px; +} +ul#user-actions2 { + padding:5px; + margin:0; + display:inline; + color:black; + background-color:#ececec; + list-style-type:none; + border-radius:3px; + -moz-border-radius:3px; +} +ul#page-actions2 li, ul#user-actions2 li { + display:inline; +} +ul#page-actions2 a, ul#user-actions2 a { + text-decoration:none; + color:black; + display:inline; + margin:0 3px; + padding:2px 0px 2px 18px; +} +ul#page-actions2 a:hover, ul#page-actions2 a:focus, ul#user-actions2 a:hover, ul#user-actions2 a:focus, +ul#page-actions-more a:hover, ul#page-actions-more a:focus{ + color: #4e7bb4; +} +/****************************/ +.hidden { + display:none; +} + +a.logout { + background:transparent url(../img/user-actions-logout.png) 0px 1px no-repeat; +} + +a.info { + background:transparent url(../img/user-info.png) 0px 1px no-repeat; +} + +a.admin { + background:transparent url(../img/user-actions-admin.png) 0px 1px no-repeat; +} +a.profile { + background:transparent url(../img/user-actions-profile.png) 0px 1px no-repeat; +} +a.create, a.edit { + background:transparent url(../img/page-tools-edit.png) 0px 1px no-repeat; +} +a.source, a.show { + background:transparent url(../img/page-tools-source.png) 0px 1px no-repeat; +} +a.revisions { + background:transparent url(../img/page-tools-revisions.png) 0px 1px no-repeat; +} +a.subscribe, a.unsubscribe { + background:transparent url(../img/page-tools-subscribe.png) 0px 1px no-repeat; +} +a.backlink { + background:transparent url(../img/page-tools-backlinks.png) 0px 1px no-repeat; +} +a.play { + background:transparent url(../img/control_play.png) 0px 1px no-repeat; +} +.time { + background:transparent url(../img/status_None.png) 0px 1px no-repeat; + padding: 2px 0px 2px 18px; + margin: 0px 3px; +} +.reconnect { + background:transparent url(../img/reconnect.png) 0px 1px no-repeat; + padding: 2px 0px 2px 18px; + margin: 0px 3px; +} +a.play:hover { + background:transparent url(../img/control_play_blue.png) 0px 1px no-repeat; +} +a.cancel { + background:transparent url(../img/control_cancel.png) 0px 1px no-repeat; +} +a.cancel:hover { + background:transparent url(../img/control_cancel_blue.png) 0px 1px no-repeat; +} +a.pause { + background:transparent url(../img/control_pause.png) 0px 1px no-repeat; +} +a.pause:hover { + background:transparent url(../img/control_pause_blue.png) 0px 1px no-repeat; + font-weight: bold; +} +a.stop { + background:transparent url(../img/control_stop.png) 0px 1px no-repeat; +} +a.stop:hover { + background:transparent url(../img/control_stop_blue.png) 0px 1px no-repeat; +} +a.add { + background:transparent url(../img/control_add.png) 0px 1px no-repeat; +} +a.add:hover { + background:transparent url(../img/control_add_blue.png) 0px 1px no-repeat; +} +a.cog { + background:transparent url(../img/cog.png) 0px 1px no-repeat; +} +#head-panel { + background:#525252 url(../img/head_bg1.png) bottom left repeat-x; +} +#head-panel h1 { + display:none; + margin:0; + text-decoration:none; + padding-top:0.8em; + padding-left:3.3em; + font-size:2.6em; + color:#eeeeec; +} +#head-panel #head-logo { + float:left; + margin:5px 0 -15px 5px; + padding:0; + overflow:visible; +} +#head-menu { + background:transparent url(../img/tabs-border-bottom.png) 0 100% repeat-x; + width:100%; + float:left; + margin:0; + padding:0; + padding-top:0.8em; +} +#head-menu ul { + list-style:none; + margin:0 1em 0 2em; +} +#head-menu ul li { + float:left; + margin:0; + margin-left:0.3em; + font-size:14px; + margin-bottom:4px; +} +#head-menu ul li.selected, #head-menu ul li:hover { + margin-bottom:0px; +} +#head-menu ul li a img { + height:22px; + width:22px; + vertical-align:middle; +} +#head-menu ul li a, #head-menu ul li a:link { + float:left; + text-decoration:none; + color:#555; + background:#eaeaea url(../img/tab-background.png) 0 100% repeat-x; + padding:3px 7px 3px 7px; + border:2px solid #ccc; + border-bottom:0px solid transparent; + padding-bottom:3px; + -moz-border-radius:5px; + border-radius:5px; +} +#head-menu ul li a:hover, #head-menu ul li a:focus { + color:#111; + padding-bottom:7px; + border-bottom:0px none transparent; + outline:none; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + -moz-border-radius-bottomright:0px; + -moz-border-radius-bottomleft:0px; +} +#head-menu ul li a:focus { + margin-bottom:-4px; +} +#head-menu ul li.selected a { + color:#3566A5; + background:#fff; + padding-bottom:7px; + border-bottom:0px none transparent; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + -moz-border-radius-bottomright:0px; + -moz-border-radius-bottomleft:0px; +} +#head-menu ul li.selected a:hover, #head-menu ul li.selected a:focus { + color:#111; +} +div#head-search-and-login { + float:right; + margin:0 1em 0 0; + background-color:#222; + padding:7px 7px 5px 5px; + color:white; + white-space: nowrap; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-bottomright:6px; + -moz-border-radius-bottomleft:6px; +} +div#head-search-and-login form { + display:inline; + padding:0 3px; +} +div#head-search-and-login form input { + border:2px solid #888; + background:#eee; + font-size:14px; + padding:2px; + border-radius:3px; + -moz-border-radius:3px; +} +div#head-search-and-login form input:focus { + background:#fff; +} +#head-search { + font-size:14px; +} +#head-username, #head-password { + width:80px; + font-size:14px; +} +#pageinfo { + clear:both; + color:#888; + padding:0.6em 0; + margin:0; +} +#foot { + font-style:normal; + color:#888; + text-align:center; +} +#foot a { + color:#aaf; +} +#foot img { + vertical-align:middle; +} +div.toc { + border:1px dotted #888; + background:#f0f0f0; + margin:1em 0 1em 1em; + float:right; + font-size:95%; +} +div.toc .tocheader { + font-weight:bold; + margin:0.5em 1em; +} +div.toc ol { + margin:1em 0.5em 1em 1em; + padding:0; +} +div.toc ol li { + margin:0; + padding:0; + margin-left:1em; +} +div.toc ol ol { + margin:0.5em 0.5em 0.5em 1em; + padding:0; +} +div.recentchanges table { + clear:both; +} +div#editor-help { + font-size:90%; + border:1px dotted #888; + padding:0ex 1ex 1ex 1ex; + background:#f7f6f2; +} +div#preview { + margin-top:1em; +} +label.block { + display:block; + text-align:right; + font-weight:bold; +} +label.simple { + display:block; + text-align:left; + font-weight:normal; +} +label.block input.edit { + width:50%; +} +/*fieldset { + width:300px; + text-align:center; + padding:0.5em; + margin:auto; +} +*/ +div.editor { + margin:0 0 0 0; +} +table { + margin:0.5em 0; + border-collapse:collapse; +} +td { + padding:0.25em; + border:1pt solid #ADB9CC; +} +td p { + margin:0; + padding:0; +} +.u { + text-decoration:underline; +} +.footnotes ul { + padding:0 2em; + margin:0 0 1em; +} +.footnotes li { + list-style:none; +} +.userpref table, .userpref td { + border:none; +} +#message { + clear:both; + padding:5px 10px; + background-color:#eee; + border-bottom:2px solid #ccc; +} +#message p { + margin:5px 0; + padding:0; + font-weight:bold; +} +#message div.buttons { + font-weight:normal; +} +.diff { + width:99%; +} +.diff-title { + background-color:#C0C0C0; +} +.searchresult dd span { + font-weight:bold; +} +.boxtext { + font-family:tahoma, arial, sans-serif; + font-size:11px; + color:#000; + float:none; + padding:3px 0 0 10px; +} +.statusbutton { + width:32px; + height:32px; + float:left; + margin-left:-32px; + margin-right:5px; + opacity:0; + cursor:pointer +} +.dlsize { + float:left; + padding-right: 8px; +} +.dlspeed { + float:left; + padding-right: 8px; +} +.package { + margin-bottom: 10px; +} +.packagename { + font-weight: bold; +} + +.child { + margin-left: 20px; +} +.child_status { + margin-right: 10px; +} +.child_secrow { + font-size: 10px; +} + +.header, .header th { + text-align: left; + font-weight: normal; + background-color:#ececec; + -moz-border-radius:5px; + border-radius:5px; +} +.progress_bar { + background: #0C0; + height: 5px; + +} + +.queue { + border: none +} + +.queue tr td { + border: none +} + +.header, .header th{ + text-align: left; + font-weight: normal; +} + + +.clearer +{ + clear: both; + height: 1px; +} + +.left +{ + float: left; +} + +.right +{ + float: right; +} + + +.setfield +{ + display: table-cell; +} + +ul.tabs li a +{ + padding: 5px 16px 4px 15px; + border: none; + font-weight: bold; + + border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + +} + + +#tabs span +{ + display: none; +} + +#tabs span.selected +{ + display: inline; +} + +#tabsback +{ + background-color: #525252; + margin: 2px 0 0; + padding: 6px 4px 1px 4px; + + border-top-right-radius: 30px; + border-top-left-radius: 3px; + -moz-border-radius-topright: 30px; + -moz-border-radius-topleft: 3px; +} +ul.tabs +{ + list-style-type: none; + margin:0; + padding: 0 40px 0 0; +} + +ul.tabs li +{ + display: inline; + margin-left: 8px; +} + + +ul.tabs li a +{ + color: #42454a; + background-color: #eaeaea; + border: 1px none #c9c3ba; + margin: 0; + text-decoration: none; + + outline: 0; + + padding: 5px 16px 4px 15px; + font-weight: bold; + + border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + +} + +ul.tabs li a.selected, ul.tabs li a:hover +{ + color: #000; + background-color: white; + + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomright: 0; + -moz-border-radius-bottomleft: 0; +} + +ul.tabs li a:hover +{ + background-color: #f1f4ee; +} + +ul.tabs li a.selected +{ + font-weight: bold; + background-color: #525252; + padding-bottom: 5px; + color: white; +} + + +#tabs-body { + position: relative; + overflow: hidden; +} + + +span.tabContent +{ + border: 2px solid #525252; + margin: 0; + padding: 0; + padding-bottom: 10px; +} + +#tabs-body > span { + display: none; +} + +#tabs-body > span.active { + display: block; +} + +.hide +{ + display: none; +} + +.settable +{ + margin: 20px; + border: none; +} +.settable td +{ + border: none; + margin: 0; + padding: 5px; +} + +.settable th{ + padding-bottom: 8px; +} + +.settable.wide td , .settable.wide th { + padding-left: 15px; + padding-right: 15px; +} + + +/*settings navbar*/ +ul.nav { + margin: -30px 0 0; + padding: 0; + list-style: none; + position: absolute; +} + + +ul.nav li { + position: relative; + float: left; + padding: 5px; +} + +ul.nav > li a { + background: white; + -moz-border-radius: 4px 4px 4px 4px; + border: 1px solid #C9C3BA; + border-bottom: medium none; + color: black; +} + +ul.nav ul { + position: absolute; + top: 26px; + left: 10px; + margin: 0; + padding: 0; + list-style: none; + border: 1px solid #AAA; + background: #f1f1f1; + -webkit-box-shadow: 1px 1px 5px #AAA; + -moz-box-shadow: 1px 1px 5px #AAA; + box-shadow: 1px 1px 5px #AAA; + cursor: pointer; +} + +ul.nav .open { + display: block; +} + +ul.nav .close { + display: none; +} + +ul.nav ul li { + float: none; + padding: 0; +} + +ul.nav ul li a { + width: 130px; + background: #f1f1f1; + padding: 3px; + display: block; + font-weight: normal; +} + +ul.nav ul li a:hover { + background: #CDCDCD; +} + +ul.nav ul ul { + left: 137px; + top: 0; +} + +.purr-wrapper{ + margin:10px; +} + +/*Purr alert styles*/ + +.purr-alert{ + margin-bottom:10px; + padding:10px; + background:#000; + font-size:13px; + font-weight:bold; + color:#FFF; + -moz-border-radius:5px; + -webkit-border-radius:5px; + /*-moz-box-shadow: 0 0 10px rgba(255,255,0,.25);*/ + width:300px; +} +.purr-alert.error{ + color:#F55; + padding-left:30px; + background:url(../img/error.png) no-repeat #000 7px 10px; + width:280px; +} +.purr-alert.success{ + color:#5F5; + padding-left:30px; + background:url(../img/success.png) no-repeat #000 7px 10px; + width:280px; +} +.purr-alert.notice{ + color:#99F; + padding-left:30px; + background:url(../img/notice.png) no-repeat #000 7px 10px; + width:280px; +} + +table.system { + border: none; + margin-left: 10px; +} + +table.system td { + border: none +} + +table.system tr > td:first-child { + font-weight: bold; + padding-right: 10px; +} diff --git a/module/web/media/default/css/log.css b/module/webui/themes/default/css/log.css index 73786bfb4..26449b244 100644 --- a/module/web/media/default/css/log.css +++ b/module/webui/themes/default/css/log.css @@ -26,7 +26,7 @@ html, body, #content } .logtable { - + margin: 0px; } .logtable td @@ -34,7 +34,6 @@ html, body, #content border: none; white-space: nowrap; - font-family: monospace; font-size: 16px; margin: 0px; @@ -69,4 +68,4 @@ td.loglevel { text-align: center; color: red; -}
\ No newline at end of file +} diff --git a/module/webui/themes/default/css/pathchooser.css b/module/webui/themes/default/css/pathchooser.css new file mode 100644 index 000000000..894cc335e --- /dev/null +++ b/module/webui/themes/default/css/pathchooser.css @@ -0,0 +1,68 @@ +table { + width: 90%; + border: 1px dotted #888888; + font-family: sans-serif; + font-size: 10pt; +} + +th { + background-color: #525252; + color: #E0E0E0; +} + +table, tr, td { + background-color: #F0F0F0; +} + +a, a:visited { + text-decoration: none; + font-weight: bold; +} + +#paths { + width: 90%; + text-align: left; +} + +.file_directory { + color: #c0c0c0; +} +.path_directory { + color: #3c3c3c; +} +.file_file { + color: #3c3c3c; +} +.path_file { + color: #c0c0c0; +} + +.parentdir { + color: #000000; + font-size: 10pt; +} +.name { + text-align: left; +} +.size { + text-align: right; +} +.type { + text-align: left; +} +.mtime { + text-align: center; +} + +.path_abs_rel { + color: #3c3c3c; + text-decoration: none; + font-weight: bold; + font-family: sans-serif; + font-size: 10pt; +} + +.path_abs_rel a { + color: #3c3c3c; + font-style: italic; +} diff --git a/module/web/media/default/css/window.css b/module/webui/themes/default/css/window.css index 12829868b..12829868b 100644 --- a/module/web/media/default/css/window.css +++ b/module/webui/themes/default/css/window.css diff --git a/module/webui/themes/default/img/MooDialog/dialog-close.png b/module/webui/themes/default/img/MooDialog/dialog-close.png Binary files differnew file mode 100644 index 000000000..81ebb88b2 --- /dev/null +++ b/module/webui/themes/default/img/MooDialog/dialog-close.png diff --git a/module/webui/themes/default/img/MooDialog/dialog-error.png b/module/webui/themes/default/img/MooDialog/dialog-error.png Binary files differnew file mode 100644 index 000000000..d70328403 --- /dev/null +++ b/module/webui/themes/default/img/MooDialog/dialog-error.png diff --git a/module/webui/themes/default/img/MooDialog/dialog-question.png b/module/webui/themes/default/img/MooDialog/dialog-question.png Binary files differnew file mode 100644 index 000000000..b0af3db5b --- /dev/null +++ b/module/webui/themes/default/img/MooDialog/dialog-question.png diff --git a/module/webui/themes/default/img/MooDialog/dialog-warning.png b/module/webui/themes/default/img/MooDialog/dialog-warning.png Binary files differnew file mode 100644 index 000000000..aad64d4be --- /dev/null +++ b/module/webui/themes/default/img/MooDialog/dialog-warning.png diff --git a/module/webui/themes/default/img/add_folder.png b/module/webui/themes/default/img/add_folder.png Binary files differnew file mode 100644 index 000000000..8acbc411b --- /dev/null +++ b/module/webui/themes/default/img/add_folder.png diff --git a/module/webui/themes/default/img/ajax-loader.gif b/module/webui/themes/default/img/ajax-loader.gif Binary files differnew file mode 100644 index 000000000..2fd8e0737 --- /dev/null +++ b/module/webui/themes/default/img/ajax-loader.gif diff --git a/module/webui/themes/default/img/arrow_refresh.png b/module/webui/themes/default/img/arrow_refresh.png Binary files differnew file mode 100644 index 000000000..0de26566d --- /dev/null +++ b/module/webui/themes/default/img/arrow_refresh.png diff --git a/module/webui/themes/default/img/arrow_right.png b/module/webui/themes/default/img/arrow_right.png Binary files differnew file mode 100644 index 000000000..b1a181923 --- /dev/null +++ b/module/webui/themes/default/img/arrow_right.png diff --git a/module/webui/themes/default/img/big_button.gif b/module/webui/themes/default/img/big_button.gif Binary files differnew file mode 100644 index 000000000..7680490ea --- /dev/null +++ b/module/webui/themes/default/img/big_button.gif diff --git a/module/webui/themes/default/img/big_button_over.gif b/module/webui/themes/default/img/big_button_over.gif Binary files differnew file mode 100644 index 000000000..2e3ee10d2 --- /dev/null +++ b/module/webui/themes/default/img/big_button_over.gif diff --git a/module/webui/themes/default/img/body.png b/module/webui/themes/default/img/body.png Binary files differnew file mode 100644 index 000000000..7ff1043e0 --- /dev/null +++ b/module/webui/themes/default/img/body.png diff --git a/module/web/media/default/img/button.png b/module/webui/themes/default/img/button.png Binary files differindex 890160614..890160614 100644 --- a/module/web/media/default/img/button.png +++ b/module/webui/themes/default/img/button.png diff --git a/module/webui/themes/default/img/closebtn.gif b/module/webui/themes/default/img/closebtn.gif Binary files differnew file mode 100644 index 000000000..3e27e6030 --- /dev/null +++ b/module/webui/themes/default/img/closebtn.gif diff --git a/module/webui/themes/default/img/cog.png b/module/webui/themes/default/img/cog.png Binary files differnew file mode 100644 index 000000000..67de2c6cc --- /dev/null +++ b/module/webui/themes/default/img/cog.png diff --git a/module/webui/themes/default/img/control_add.png b/module/webui/themes/default/img/control_add.png Binary files differnew file mode 100644 index 000000000..d39886893 --- /dev/null +++ b/module/webui/themes/default/img/control_add.png diff --git a/module/webui/themes/default/img/control_add_blue.png b/module/webui/themes/default/img/control_add_blue.png Binary files differnew file mode 100644 index 000000000..d11b7f41d --- /dev/null +++ b/module/webui/themes/default/img/control_add_blue.png diff --git a/icons/add_small.png b/module/webui/themes/default/img/control_cancel.png Binary files differindex 4dc88b09b..7b9bc3fba 100644 --- a/icons/add_small.png +++ b/module/webui/themes/default/img/control_cancel.png diff --git a/module/webui/themes/default/img/control_cancel_blue.png b/module/webui/themes/default/img/control_cancel_blue.png Binary files differnew file mode 100644 index 000000000..0c5c96ce3 --- /dev/null +++ b/module/webui/themes/default/img/control_cancel_blue.png diff --git a/module/webui/themes/default/img/control_pause.png b/module/webui/themes/default/img/control_pause.png Binary files differnew file mode 100644 index 000000000..2d9ce9c4e --- /dev/null +++ b/module/webui/themes/default/img/control_pause.png diff --git a/module/webui/themes/default/img/control_pause_blue.png b/module/webui/themes/default/img/control_pause_blue.png Binary files differnew file mode 100644 index 000000000..ec61099b0 --- /dev/null +++ b/module/webui/themes/default/img/control_pause_blue.png diff --git a/module/webui/themes/default/img/control_play.png b/module/webui/themes/default/img/control_play.png Binary files differnew file mode 100644 index 000000000..0846555d0 --- /dev/null +++ b/module/webui/themes/default/img/control_play.png diff --git a/module/webui/themes/default/img/control_play_blue.png b/module/webui/themes/default/img/control_play_blue.png Binary files differnew file mode 100644 index 000000000..f8c8ec683 --- /dev/null +++ b/module/webui/themes/default/img/control_play_blue.png diff --git a/module/webui/themes/default/img/control_stop.png b/module/webui/themes/default/img/control_stop.png Binary files differnew file mode 100644 index 000000000..893bb60e5 --- /dev/null +++ b/module/webui/themes/default/img/control_stop.png diff --git a/module/webui/themes/default/img/control_stop_blue.png b/module/webui/themes/default/img/control_stop_blue.png Binary files differnew file mode 100644 index 000000000..e6f75d232 --- /dev/null +++ b/module/webui/themes/default/img/control_stop_blue.png diff --git a/module/webui/themes/default/img/delete.png b/module/webui/themes/default/img/delete.png Binary files differnew file mode 100644 index 000000000..08f249365 --- /dev/null +++ b/module/webui/themes/default/img/delete.png diff --git a/module/webui/themes/default/img/drag_corner.gif b/module/webui/themes/default/img/drag_corner.gif Binary files differnew file mode 100644 index 000000000..befb1adf1 --- /dev/null +++ b/module/webui/themes/default/img/drag_corner.gif diff --git a/module/webui/themes/default/img/error.png b/module/webui/themes/default/img/error.png Binary files differnew file mode 100644 index 000000000..c37bd062e --- /dev/null +++ b/module/webui/themes/default/img/error.png diff --git a/module/webui/themes/default/img/folder.png b/module/webui/themes/default/img/folder.png Binary files differnew file mode 100644 index 000000000..784e8fa48 --- /dev/null +++ b/module/webui/themes/default/img/folder.png diff --git a/module/webui/themes/default/img/full.png b/module/webui/themes/default/img/full.png Binary files differnew file mode 100644 index 000000000..fea52af76 --- /dev/null +++ b/module/webui/themes/default/img/full.png diff --git a/module/webui/themes/default/img/head-login.png b/module/webui/themes/default/img/head-login.png Binary files differnew file mode 100644 index 000000000..b59b7cbbf --- /dev/null +++ b/module/webui/themes/default/img/head-login.png diff --git a/module/webui/themes/default/img/head-menu-collector.png b/module/webui/themes/default/img/head-menu-collector.png Binary files differnew file mode 100644 index 000000000..861be40bc --- /dev/null +++ b/module/webui/themes/default/img/head-menu-collector.png diff --git a/module/webui/themes/default/img/head-menu-config.png b/module/webui/themes/default/img/head-menu-config.png Binary files differnew file mode 100644 index 000000000..bbf43d4f3 --- /dev/null +++ b/module/webui/themes/default/img/head-menu-config.png diff --git a/module/webui/themes/default/img/head-menu-development.png b/module/webui/themes/default/img/head-menu-development.png Binary files differnew file mode 100644 index 000000000..fad150fe1 --- /dev/null +++ b/module/webui/themes/default/img/head-menu-development.png diff --git a/module/webui/themes/default/img/head-menu-download.png b/module/webui/themes/default/img/head-menu-download.png Binary files differnew file mode 100644 index 000000000..98c5da9db --- /dev/null +++ b/module/webui/themes/default/img/head-menu-download.png diff --git a/module/webui/themes/default/img/head-menu-home.png b/module/webui/themes/default/img/head-menu-home.png Binary files differnew file mode 100644 index 000000000..9d62109aa --- /dev/null +++ b/module/webui/themes/default/img/head-menu-home.png diff --git a/module/webui/themes/default/img/head-menu-index.png b/module/webui/themes/default/img/head-menu-index.png Binary files differnew file mode 100644 index 000000000..44d631064 --- /dev/null +++ b/module/webui/themes/default/img/head-menu-index.png diff --git a/module/webui/themes/default/img/head-menu-news.png b/module/webui/themes/default/img/head-menu-news.png Binary files differnew file mode 100644 index 000000000..43950ebc9 --- /dev/null +++ b/module/webui/themes/default/img/head-menu-news.png diff --git a/module/webui/themes/default/img/head-menu-queue.png b/module/webui/themes/default/img/head-menu-queue.png Binary files differnew file mode 100644 index 000000000..be98793ce --- /dev/null +++ b/module/webui/themes/default/img/head-menu-queue.png diff --git a/module/webui/themes/default/img/head-menu-recent.png b/module/webui/themes/default/img/head-menu-recent.png Binary files differnew file mode 100644 index 000000000..fc9b0497f --- /dev/null +++ b/module/webui/themes/default/img/head-menu-recent.png diff --git a/module/webui/themes/default/img/head-menu-wiki.png b/module/webui/themes/default/img/head-menu-wiki.png Binary files differnew file mode 100644 index 000000000..07cf0102d --- /dev/null +++ b/module/webui/themes/default/img/head-menu-wiki.png diff --git a/module/webui/themes/default/img/head-search-noshadow.png b/module/webui/themes/default/img/head-search-noshadow.png Binary files differnew file mode 100644 index 000000000..aafdae015 --- /dev/null +++ b/module/webui/themes/default/img/head-search-noshadow.png diff --git a/module/webui/themes/default/img/head_bg1.png b/module/webui/themes/default/img/head_bg1.png Binary files differnew file mode 100644 index 000000000..f2848c3cc --- /dev/null +++ b/module/webui/themes/default/img/head_bg1.png diff --git a/module/webui/themes/default/img/images.png b/module/webui/themes/default/img/images.png Binary files differnew file mode 100644 index 000000000..184860d1e --- /dev/null +++ b/module/webui/themes/default/img/images.png diff --git a/module/webui/themes/default/img/notice.png b/module/webui/themes/default/img/notice.png Binary files differnew file mode 100644 index 000000000..12cd1aef9 --- /dev/null +++ b/module/webui/themes/default/img/notice.png diff --git a/module/webui/themes/default/img/package_go.png b/module/webui/themes/default/img/package_go.png Binary files differnew file mode 100644 index 000000000..aace63ad6 --- /dev/null +++ b/module/webui/themes/default/img/package_go.png diff --git a/module/webui/themes/default/img/page-tools-backlinks.png b/module/webui/themes/default/img/page-tools-backlinks.png Binary files differnew file mode 100644 index 000000000..3eb6a9ce3 --- /dev/null +++ b/module/webui/themes/default/img/page-tools-backlinks.png diff --git a/module/webui/themes/default/img/page-tools-edit.png b/module/webui/themes/default/img/page-tools-edit.png Binary files differnew file mode 100644 index 000000000..188e1c12b --- /dev/null +++ b/module/webui/themes/default/img/page-tools-edit.png diff --git a/module/webui/themes/default/img/page-tools-revisions.png b/module/webui/themes/default/img/page-tools-revisions.png Binary files differnew file mode 100644 index 000000000..5c3b8587f --- /dev/null +++ b/module/webui/themes/default/img/page-tools-revisions.png diff --git a/module/webui/themes/default/img/parseUri.png b/module/webui/themes/default/img/parseUri.png Binary files differnew file mode 100644 index 000000000..937bded9d --- /dev/null +++ b/module/webui/themes/default/img/parseUri.png diff --git a/module/webui/themes/default/img/pencil.png b/module/webui/themes/default/img/pencil.png Binary files differnew file mode 100644 index 000000000..0bfecd50e --- /dev/null +++ b/module/webui/themes/default/img/pencil.png diff --git a/module/web/media/default/img/pyload-logo-edited3.5-new-font-small.png b/module/webui/themes/default/img/pyload-logo.png Binary files differindex 2443cd8b1..2443cd8b1 100644 --- a/module/web/media/default/img/pyload-logo-edited3.5-new-font-small.png +++ b/module/webui/themes/default/img/pyload-logo.png diff --git a/module/webui/themes/default/img/reconnect.png b/module/webui/themes/default/img/reconnect.png Binary files differnew file mode 100644 index 000000000..49b269145 --- /dev/null +++ b/module/webui/themes/default/img/reconnect.png diff --git a/module/webui/themes/default/img/status_None.png b/module/webui/themes/default/img/status_None.png Binary files differnew file mode 100644 index 000000000..293b13f77 --- /dev/null +++ b/module/webui/themes/default/img/status_None.png diff --git a/module/webui/themes/default/img/status_downloading.png b/module/webui/themes/default/img/status_downloading.png Binary files differnew file mode 100644 index 000000000..fb4ebc850 --- /dev/null +++ b/module/webui/themes/default/img/status_downloading.png diff --git a/module/webui/themes/default/img/status_failed.png b/module/webui/themes/default/img/status_failed.png Binary files differnew file mode 100644 index 000000000..c37bd062e --- /dev/null +++ b/module/webui/themes/default/img/status_failed.png diff --git a/module/webui/themes/default/img/status_finished.png b/module/webui/themes/default/img/status_finished.png Binary files differnew file mode 100644 index 000000000..89c8129a4 --- /dev/null +++ b/module/webui/themes/default/img/status_finished.png diff --git a/module/webui/themes/default/img/status_offline.png b/module/webui/themes/default/img/status_offline.png Binary files differnew file mode 100644 index 000000000..0cfd58596 --- /dev/null +++ b/module/webui/themes/default/img/status_offline.png diff --git a/module/webui/themes/default/img/status_proc.png b/module/webui/themes/default/img/status_proc.png Binary files differnew file mode 100644 index 000000000..67de2c6cc --- /dev/null +++ b/module/webui/themes/default/img/status_proc.png diff --git a/module/webui/themes/default/img/status_queue.png b/module/webui/themes/default/img/status_queue.png Binary files differnew file mode 100644 index 000000000..293b13f77 --- /dev/null +++ b/module/webui/themes/default/img/status_queue.png diff --git a/module/webui/themes/default/img/status_waiting.png b/module/webui/themes/default/img/status_waiting.png Binary files differnew file mode 100644 index 000000000..2842cc338 --- /dev/null +++ b/module/webui/themes/default/img/status_waiting.png diff --git a/module/webui/themes/default/img/success.png b/module/webui/themes/default/img/success.png Binary files differnew file mode 100644 index 000000000..89c8129a4 --- /dev/null +++ b/module/webui/themes/default/img/success.png diff --git a/module/web/media/default/img/tab-background.png b/module/webui/themes/default/img/tab-background.png Binary files differindex 29a5d1991..29a5d1991 100644 --- a/module/web/media/default/img/tab-background.png +++ b/module/webui/themes/default/img/tab-background.png diff --git a/module/webui/themes/default/img/tabs-border-bottom.png b/module/webui/themes/default/img/tabs-border-bottom.png Binary files differnew file mode 100644 index 000000000..02440f428 --- /dev/null +++ b/module/webui/themes/default/img/tabs-border-bottom.png diff --git a/module/webui/themes/default/img/user-actions-logout.png b/module/webui/themes/default/img/user-actions-logout.png Binary files differnew file mode 100644 index 000000000..0010931e2 --- /dev/null +++ b/module/webui/themes/default/img/user-actions-logout.png diff --git a/module/webui/themes/default/img/user-actions-profile.png b/module/webui/themes/default/img/user-actions-profile.png Binary files differnew file mode 100644 index 000000000..46573fff6 --- /dev/null +++ b/module/webui/themes/default/img/user-actions-profile.png diff --git a/module/webui/themes/default/img/user-info.png b/module/webui/themes/default/img/user-info.png Binary files differnew file mode 100644 index 000000000..6e643100f --- /dev/null +++ b/module/webui/themes/default/img/user-info.png diff --git a/module/webui/themes/default/js/render/admin.coffee b/module/webui/themes/default/js/render/admin.coffee new file mode 100644 index 000000000..5afbcbb66 --- /dev/null +++ b/module/webui/themes/default/js/render/admin.coffee @@ -0,0 +1,58 @@ +root = this + +window.addEvent "domready", -> + + root.passwordDialog = new MooDialog {destroyOnHide: false} + root.passwordDialog.setContent $ 'password_box' + + $("login_password_reset").addEvent "click", (e) -> root.passwordDialog.close() + $("login_password_button").addEvent "click", (e) -> + + newpw = $("login_new_password").get("value") + newpw2 = $("login_new_password2").get("value") + + if newpw is newpw2 + form = $("password_form") + form.set "send", { + onSuccess: (data) -> + root.notify.alert "Success", { + 'className': 'success' + } + onFailure: (data) -> + root.notify.alert "Error", { + 'className': 'error' + } + } + + form.send() + + root.passwordDialog.close() + else + alert '{{_("Passwords did not match.")}}' + + e.stop() + + for item in $$(".change_password") + id = item.get("id") + user = id.split("|")[1] + $("user_login").set("value", user) + item.addEvent "click", (e) -> root.passwordDialog.open() + + $('quit-pyload').addEvent "click", (e) -> + new MooDialog.Confirm "{{_('You are really sure you want to quit pyLoad?')}}", -> + new Request.JSON({ + url: '/api/kill' + method: 'get' + }).send() + , -> + e.stop() + + $('restart-pyload').addEvent "click", (e) -> + new MooDialog.Confirm "{{_('Are you sure you want to restart pyLoad?')}}", -> + new Request.JSON({ + url: '/api/restart' + method: 'get' + onSuccess: (data) -> alert "{{_('pyLoad restarted')}}" + }).send() + , -> + e.stop() diff --git a/module/webui/themes/default/js/render/admin.min.js b/module/webui/themes/default/js/render/admin.min.js new file mode 100644 index 000000000..94a5e494d --- /dev/null +++ b/module/webui/themes/default/js/render/admin.min.js @@ -0,0 +1,3 @@ +{% autoescape true %} +var root;root=this;window.addEvent("domready",function(){var f,c,b,e,a,d;root.passwordDialog=new MooDialog({destroyOnHide:false});root.passwordDialog.setContent($("password_box"));$("login_password_reset").addEvent("click",function(g){return root.passwordDialog.close()});$("login_password_button").addEvent("click",function(j){var h,i,g;i=$("login_new_password").get("value");g=$("login_new_password2").get("value");if(i===g){h=$("password_form");h.set("send",{onSuccess:function(k){return root.notify.alert("Success",{className:"success"})},onFailure:function(k){return root.notify.alert("Error",{className:"error"})}});h.send();root.passwordDialog.close()}else{alert('{{_("Passwords did not match.")}}')}return j.stop()});d=$$(".change_password");for(e=0,a=d.length;e<a;e++){c=d[e];f=c.get("id");b=f.split("|")[1];$("user_login").set("value",b);c.addEvent("click",function(g){return root.passwordDialog.open()})}$("quit-pyload").addEvent("click",function(g){new MooDialog.Confirm("{{_('You are really sure you want to quit pyLoad?')}}",function(){return new Request.JSON({url:"/api/kill",method:"get"}).send()},function(){});return g.stop()});return $("restart-pyload").addEvent("click",function(g){new MooDialog.Confirm("{{_('Are you sure you want to restart pyLoad?')}}",function(){return new Request.JSON({url:"/api/restart",method:"get",onSuccess:function(h){return alert("{{_('pyLoad restarted')}}")}}).send()},function(){});return g.stop()})}); +{% endautoescape %} diff --git a/module/webui/themes/default/js/render/base.coffee b/module/webui/themes/default/js/render/base.coffee new file mode 100644 index 000000000..07b8bfb6f --- /dev/null +++ b/module/webui/themes/default/js/render/base.coffee @@ -0,0 +1,177 @@ +# External scope +root = this + +# helper functions +humanFileSize = (size) -> + filesizename = new Array("B", "KiB", "MiB", "GiB", "TiB", "PiB") + loga = Math.log(size) / Math.log(1024) + i = Math.floor(loga) + a = Math.pow(1024, i) + if size is 0 then "0 B" else (Math.round(size * 100 / a) / 100 + " " + filesizename[i]) + + +parseUri = () -> + oldString = $("add_links").value + regxp = new RegExp('(ht|f)tp(s?):\/\/[a-zA-Z0-9\-\.\/\?=_&%#]+[<| |\"|\'|\r|\n|\t]{1}', 'g') + resu = oldString.match regxp + return if resu == null + res = "" + + for part in resu + if part.indexOf(" ") != -1 + res = res + part.replace(" ", " \n") + else if part.indexOf("\t") != -1 + res = res + part.replace("\t", " \n") + else if part.indexOf("\r") != -1 + res = res + part.replace("\r", " \n") + else if part.indexOf("\"") != -1 + res = res + part.replace("\"", " \n") + else if part.indexOf("<") != -1 + res = res + part.replace("<", " \n") + else if part.indexOf("'") != -1 + res = res + part.replace("'", " \n") + else + res = res + part.replace("\n", " \n") + + $("add_links").value = res + + +Array::remove = (from, to) -> + rest = this.slice((to || from) + 1 || this.length) + this.length = from < 0 ? this.length + from : from + return [] if this.length == 0 + return this.push.apply(this, rest) + + +document.addEvent "domready", -> + + # global notification + root.notify = new Purr { + 'mode': 'top' + 'position': 'center' + } + + root.captchaBox = new MooDialog {destroyOnHide: false} + root.captchaBox.setContent $ 'cap_box' + + root.addBox = new MooDialog {destroyOnHide: false} + root.addBox.setContent $ 'add_box' + + $('add_form').onsubmit = -> + $('add_form').target = 'upload_target' + if $('add_name').value is "" and $('add_file').value is "" + alert '{{_("Please Enter a packagename.")}}' + return false + else + root.addBox.close() + return true + + $('add_reset').addEvent 'click', -> root.addBox.close() + + $('action_add').addEvent 'click', -> $("add_form").reset(); root.addBox.open() + $('action_play').addEvent 'click', -> new Request({method: 'get', url: '/api/unpauseServer'}).send() + $('action_cancel').addEvent 'click', -> new Request({method: 'get', url: '/api/stopAllDownloads'}).send() + $('action_stop').addEvent 'click', -> new Request({method: 'get', url: '/api/pauseServer'}).send() + + + # captcha events + + $('cap_info').addEvent 'click', -> + load_captcha "get", "" + root.captchaBox.open() + $('cap_reset').addEvent 'click', -> root.captchaBox.close() + $('cap_form').addEvent 'submit', (e) -> + submit_captcha() + e.stop() + + $('cap_positional').addEvent 'click', on_captcha_click + + new Request.JSON({ + url: "/json/status" + onSuccess: LoadJsonToContent + secure: false + async: true + initialDelay: 0 + delay: 4000 + limit: 3000 + }).startTimer() + + +LoadJsonToContent = (data) -> + $("speed").set 'text', humanFileSize(data.speed)+"/s" + $("aktiv").set 'text', data.active + $("aktiv_from").set 'text', data.queue + $("aktiv_total").set 'text', data.total + + if data.captcha + if $("cap_info").getStyle("display") != "inline" + $("cap_info").setStyle 'display', 'inline' + root.notify.alert '{{_("New Captcha Request")}}', { + 'className': 'notify' + } + else + $("cap_info").setStyle 'display', 'none' + + + if data.download + $("time").set 'text', ' {{_("on")}}' + $("time").setStyle 'background-color', "#8ffc25" + else + $("time").set 'text', ' {{_("off")}}' + $("time").setStyle 'background-color', "#fc6e26" + + if data.reconnect + $("reconnect").set 'text', ' {{_("on")}}' + $("reconnect").setStyle 'background-color', "#8ffc25" + else + $("reconnect").set 'text', ' {{_("off")}}' + $("reconnect").setStyle 'background-color', "#fc6e26" + + return null + + +set_captcha = (data) -> + $('cap_id').set 'value', data.id + if (data.result_type is 'textual') + $('cap_textual_img').set 'src', data.src + $('cap_title').set 'text', '{{_("Please read the text on the captcha.")}}' + $('cap_submit').setStyle 'display', 'inline' + $('cap_textual').setStyle 'display', 'block' + $('cap_positional').setStyle 'display', 'none' + + else if (data.result_type == 'positional') + $('cap_positional_img').set('src', data.src) + $('cap_title').set('text', '{{_("Please click on the right captcha position.")}}') + $('cap_submit').setStyle('display', 'none') + $('cap_textual').setStyle('display', 'none') + + +load_captcha = (method, post) -> + new Request.JSON({ + url: "/json/set_captcha" + onSuccess: (data) -> set_captcha(data) if data.captcha else clear_captcha() + secure: false + async: true + method: method + }).send(post) + + +clear_captcha = -> + $('cap_textual').setStyle 'display', 'none' + $('cap_textual_img').set 'src', '' + $('cap_positional').setStyle 'display', 'none' + $('cap_positional_img').set 'src', '' + $('cap_title').set 'text', '{{_("No Captchas to read.")}}' + + +submit_captcha = -> + load_captcha("post", "cap_id=" + $('cap_id').get('value') + "&cap_result=" + $('cap_result').get('value') ) + $('cap_result').set('value', '') + + +on_captcha_click = (e) -> + position = e.target.getPosition() + x = e.page.x - position.x + y = e.page.y - position.y + $('cap_result').value = x + "," + y + submit_captcha() diff --git a/module/webui/themes/default/js/render/base.min.js b/module/webui/themes/default/js/render/base.min.js new file mode 100644 index 000000000..1ba1d73f9 --- /dev/null +++ b/module/webui/themes/default/js/render/base.min.js @@ -0,0 +1,3 @@ +{% autoescape true %} +var LoadJsonToContent,clear_captcha,humanFileSize,load_captcha,on_captcha_click,parseUri,root,set_captcha,submit_captcha;root=this;humanFileSize=function(f){var c,d,e,b;d=new Array("B","KiB","MiB","GiB","TiB","PiB");b=Math.log(f)/Math.log(1024);e=Math.floor(b);c=Math.pow(1024,e);if(f===0){return"0 B"}else{return Math.round(f*100/c)/100+" "+d[e]}};parseUri=function(){var b,c,g,e,d,f,a;b=$("add_links").value;g=new RegExp("(ht|f)tp(s?)://[a-zA-Z0-9-./?=_&%#]+[<| |\"|'|\r|\n|\t]{1}","g");d=b.match(g);if(d===null){return}e="";for(f=0,a=d.length;f<a;f++){c=d[f];if(c.indexOf(" ")!==-1){e=e+c.replace(" "," \n")}else{if(c.indexOf("\t")!==-1){e=e+c.replace("\t"," \n")}else{if(c.indexOf("\r")!==-1){e=e+c.replace("\r"," \n")}else{if(c.indexOf('"')!==-1){e=e+c.replace('"'," \n")}else{if(c.indexOf("<")!==-1){e=e+c.replace("<"," \n")}else{if(c.indexOf("'")!==-1){e=e+c.replace("'"," \n")}else{e=e+c.replace("\n"," \n")}}}}}}}return $("add_links").value=e};Array.prototype.remove=function(d,c){var a,b;a=this.slice((c||d)+1||this.length);this.length=(b=d<0)!=null?b:this.length+{from:d};if(this.length===0){return[]}return this.push.apply(this,a)};document.addEvent("domready",function(){root.notify=new Purr({mode:"top",position:"center"});root.captchaBox=new MooDialog({destroyOnHide:false});root.captchaBox.setContent($("cap_box"));root.addBox=new MooDialog({destroyOnHide:false});root.addBox.setContent($("add_box"));$("add_form").onsubmit=function(){$("add_form").target="upload_target";if($("add_name").value===""&&$("add_file").value===""){alert('{{_("Please Enter a packagename.")}}');return false}else{root.addBox.close();return true}};$("add_reset").addEvent("click",function(){return root.addBox.close()});$("action_add").addEvent("click",function(){$("add_form").reset();return root.addBox.open()});$("action_play").addEvent("click",function(){return new Request({method:"get",url:"/api/unpauseServer"}).send()});$("action_cancel").addEvent("click",function(){return new Request({method:"get",url:"/api/stopAllDownloads"}).send()});$("action_stop").addEvent("click",function(){return new Request({method:"get",url:"/api/pauseServer"}).send()});$("cap_info").addEvent("click",function(){load_captcha("get","");return root.captchaBox.open()});$("cap_reset").addEvent("click",function(){return root.captchaBox.close()});$("cap_form").addEvent("submit",function(a){submit_captcha();return a.stop()});$("cap_positional").addEvent("click",on_captcha_click);return new Request.JSON({url:"/json/status",onSuccess:LoadJsonToContent,secure:false,async:true,initialDelay:0,delay:4000,limit:3000}).startTimer()});LoadJsonToContent=function(a){$("speed").set("text",humanFileSize(a.speed)+"/s");$("aktiv").set("text",a.active);$("aktiv_from").set("text",a.queue);$("aktiv_total").set("text",a.total);if(a.captcha){if($("cap_info").getStyle("display")!=="inline"){$("cap_info").setStyle("display","inline");root.notify.alert('{{_("New Captcha Request")}}',{className:"notify"})}}else{$("cap_info").setStyle("display","none")}if(a.download){$("time").set("text",' {{_("on")}}');$("time").setStyle("background-color","#8ffc25")}else{$("time").set("text",' {{_("off")}}');$("time").setStyle("background-color","#fc6e26")}if(a.reconnect){$("reconnect").set("text",' {{_("on")}}');$("reconnect").setStyle("background-color","#8ffc25")}else{$("reconnect").set("text",' {{_("off")}}');$("reconnect").setStyle("background-color","#fc6e26")}return null};set_captcha=function(a){$("cap_id").set("value",a.id);if(a.result_type==="textual"){$("cap_textual_img").set("src",a.src);$("cap_title").set("text",'{{_("Please read the text on the captcha.")}}');$("cap_submit").setStyle("display","inline");$("cap_textual").setStyle("display","block");return $("cap_positional").setStyle("display","none")}else{if(a.result_type==="positional"){$("cap_positional_img").set("src",a.src);$("cap_title").set("text",'{{_("Please click on the right captcha position.")}}');$("cap_submit").setStyle("display","none");return $("cap_textual").setStyle("display","none")}}};load_captcha=function(b,a){return new Request.JSON({url:"/json/set_captcha",onSuccess:function(c){return set_captcha(c)(c.captcha?void 0:clear_captcha())},secure:false,async:true,method:b}).send(a)};clear_captcha=function(){$("cap_textual").setStyle("display","none");$("cap_textual_img").set("src","");$("cap_positional").setStyle("display","none");$("cap_positional_img").set("src","");return $("cap_title").set("text",'{{_("No Captchas to read.")}}')};submit_captcha=function(){load_captcha("post","cap_id="+$("cap_id").get("value")+"&cap_result="+$("cap_result").get("value"));$("cap_result").set("value","");return false};on_captcha_click=function(c){var b,a,d;b=c.target.getPosition();a=c.page.x-b.x;d=c.page.y-b.y;$("cap_result").value=a+","+d;return submit_captcha()}; +{% endautoescape %} diff --git a/module/web/templates/default/filemanager_ui.js b/module/webui/themes/default/js/render/filemanager.js index ed64ab69d..f1ebed93f 100644 --- a/module/web/templates/default/filemanager_ui.js +++ b/module/webui/themes/default/js/render/filemanager.js @@ -12,7 +12,7 @@ document.addEvent("domready", function() { $('delete_reset').addEvent('click', function() { hide_confirm_box() }); - + /*$('filemanager_actions_list').getChildren("li").each(function(action) { var action_name = action.className; if(functions[action.className] != undefined) @@ -108,7 +108,7 @@ var Item = new Class({ this.actions["rename"] = this.rename; this.actions["mkdir"] = this.mkdir; this.parseElement(); - + var pname = this.ele.getElements("span")[0]; this.buttons = new Fx.Tween(this.ele.getElements(".buttons")[0], {link: "cancel"}); this.buttons.set("opacity", 0); @@ -151,7 +151,7 @@ var Item = new Class({ reorderElements: function() { //TODO sort the main ul again (to keep data ordered after renaming something) }, - + del: function(event) { $("confirm_form").removeEvents("submit"); $("confirm_form").addEvent("submit", this.deleteDirectory.bind(this)); @@ -161,13 +161,13 @@ var Item = new Class({ show_confirm_box(); event.stop(); }, - + deleteDirectory: function(event) { hide_confirm_box(); new Request.JSON({ method: 'POST', url: "/json/filemanager/delete", - data: {"path": this.path, "name": this.name}, + data: {'path': this.path, 'name': this.name}, onSuccess: function(data) { if(data.response == "success") { @@ -180,7 +180,7 @@ var Item = new Class({ var div = new Element("div", { 'html': '{{ _("Folder is empty") }}' }); div.replaces(ul); } - + indicateSuccess(); } else { @@ -193,7 +193,7 @@ var Item = new Class({ event.stop(); }, - + rename: function(event) { $("rename_form").removeEvents("submit"); $("rename_form").addEvent("submit", this.renameDirectory.bind(this)); @@ -201,7 +201,7 @@ var Item = new Class({ $("path").set("value", this.path); $("old_name").set("value", this.name); $("new_name").set("value", this.name); - + show_rename_box(); event.stop(); }, @@ -229,19 +229,19 @@ var Item = new Class({ event.stop(); }, - + mkdir: function(event) { new Request.JSON({ method: 'POST', url: "/json/filemanager/mkdir", - data: {"path": this.path + "/" + this.name, "name": '{{_("New folder")}}'}, + data: {'path': this.path + "/" + this.name, 'name': '{{_("New folder")}}'}, onSuccess: function(data) { if(data.response == "success") { new Request.HTML({ method: 'POST', url: "/filemanager/get_dir", - data: {"path": data.path, "name": data.name}, + data: {'path': data.path, 'name': data.name}, onSuccess: function(li) { //add node as first child of ul var ul = this.ele.getChildren('ul')[0]; @@ -249,7 +249,7 @@ var Item = new Class({ { //remove the "Folder Empty" div this.ele.getChildren('div').dispose(); - + //create new ul to contain subfolder ul = new Element("ul"); ul.inject(this.ele, 'bottom'); @@ -270,10 +270,10 @@ var Item = new Class({ }.bind(this), onFailure: indicateFail }).send(); - + event.stop(); }, - + toggle: function() { var child = this.ele.getElement('ul'); if(child == null) diff --git a/module/webui/themes/default/js/render/package.js b/module/webui/themes/default/js/render/package.js new file mode 100644 index 000000000..659a8e6fc --- /dev/null +++ b/module/webui/themes/default/js/render/package.js @@ -0,0 +1,376 @@ +var root = this; + +document.addEvent("domready", function() { + root.load = new Fx.Tween($("load-indicator"), {link: "cancel"}); + root.load.set("opacity", 0); + + + root.packageBox = new MooDialog({destroyOnHide: false}); + root.packageBox.setContent($('pack_box')); + + $('pack_reset').addEvent('click', function() { + $('pack_form').reset(); + root.packageBox.close(); + }); +}); + +function indicateLoad() { + //$("load-indicator").reveal(); + root.load.start("opacity", 1) +} + +function indicateFinish() { + root.load.start("opacity", 0) +} + +function indicateSuccess() { + indicateFinish(); + root.notify.alert('{{_("Success")}}.', { + 'className': 'success' + }); +} + +function indicateFail() { + indicateFinish(); + root.notify.alert('{{_("Failed")}}.', { + 'className': 'error' + }); +} + +var PackageUI = new Class({ + initialize: function(url, type) { + this.url = url; + this.type = type; + this.packages = []; + this.parsePackages(); + + this.sorts = new Sortables($("package-list"), { + constrain: false, + clone: true, + revert: true, + opacity: 0.4, + handle: ".package_drag", + onComplete: this.saveSort.bind(this) + }); + + $("del_finished").addEvent("click", this.deleteFinished.bind(this)); + $("restart_failed").addEvent("click", this.restartFailed.bind(this)); + + }, + + parsePackages: function() { + $("package-list").getChildren("li").each(function(ele) { + var id = ele.getFirst().get("id").match(/[0-9]+/); + this.packages.push(new Package(this, id, ele)) + }.bind(this)) + }, + + loadPackages: function() { + }, + + deleteFinished: function() { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/api/deleteFinished', + onSuccess: function(data) { + if (data.length > 0) { + window.location.reload() + } else { + this.packages.each(function(pack) { + pack.close(); + }); + indicateSuccess(); + } + }.bind(this), + onFailure: indicateFail + }).send(); + }, + + restartFailed: function() { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/api/restartFailed', + onSuccess: function(data) { + this.packages.each(function(pack) { + pack.close(); + }); + indicateSuccess(); + }.bind(this), + onFailure: indicateFail + }).send(); + }, + + startSort: function(ele, copy) { + }, + + saveSort: function(ele, copy) { + var order = []; + this.sorts.serialize(function(li, pos) { + if (li == ele && ele.retrieve("order") != pos) { + order.push(ele.retrieve("pid") + "|" + pos) + } + li.store("order", pos) + }); + if (order.length > 0) { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/json/package_order/' + order[0], + onSuccess: indicateFinish, + onFailure: indicateFail + }).send(); + } + } + +}); + +var Package = new Class({ + initialize: function(ui, id, ele, data) { + this.ui = ui; + this.id = id; + this.linksLoaded = false; + + if (!ele) { + this.createElement(data); + } else { + this.ele = ele; + this.order = ele.getElements("div.order")[0].get("html"); + this.ele.store("order", this.order); + this.ele.store("pid", this.id); + this.parseElement(); + } + + var pname = this.ele.getElements(".packagename")[0]; + this.buttons = new Fx.Tween(this.ele.getElements(".buttons")[0], {link: "cancel"}); + this.buttons.set("opacity", 0); + + pname.addEvent("mouseenter", function(e) { + this.buttons.start("opacity", 1) + }.bind(this)); + + pname.addEvent("mouseleave", function(e) { + this.buttons.start("opacity", 0) + }.bind(this)); + + + }, + + createElement: function() { + alert("create") + }, + + parseElement: function() { + var imgs = this.ele.getElements('img'); + + this.name = this.ele.getElements('.name')[0]; + this.folder = this.ele.getElements('.folder')[0]; + this.password = this.ele.getElements('.password')[0]; + + imgs[1].addEvent('click', this.deletePackage.bind(this)); + imgs[2].addEvent('click', this.restartPackage.bind(this)); + imgs[3].addEvent('click', this.editPackage.bind(this)); + imgs[4].addEvent('click', this.movePackage.bind(this)); + + this.ele.getElement('.packagename').addEvent('click', this.toggle.bind(this)); + + }, + + loadLinks: function() { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/json/package/' + this.id, + onSuccess: this.createLinks.bind(this), + onFailure: indicateFail + }).send(); + }, + + createLinks: function(data) { + var ul = $("sort_children_{id}".substitute({'id': this.id})); + ul.set("html", ""); + data.links.each(function(link) { + link.id = link.fid; + var li = new Element("li", { + 'style': { + 'margin-left': 0 + } + }); + + var html = "<span style='cursor: move' class='child_status sorthandle'><img src='../img/{icon}' style='width: 12px; height:12px;'/></span>\n".substitute({'icon': link.icon}); + html += "<span style='font-size: 15px'><a href=\"{url}\" target=\"_blank\">{name}</a></span><br /><div class='child_secrow'>".substitute({'url': link.url, 'name': link.name}); + html += "<span class='child_status'>{statusmsg}</span>{error} ".substitute({'statusmsg': link.statusmsg, 'error':link.error}); + html += "<span class='child_status'>{format_size}</span>".substitute({'format_size': link.format_size}); + html += "<span class='child_status'>{plugin}</span> ".substitute({'plugin': link.plugin}); + html += "<img title='{{_(\"Delete Link\")}}' style='cursor: pointer;' width='10px' height='10px' src='../img/delete.png' /> "; + html += "<img title='{{_(\"Restart Link\")}}' style='cursor: pointer;margin-left: -4px' width='10px' height='10px' src='../img/arrow_refresh.png' /></div>"; + + var div = new Element("div", { + 'id': "file_" + link.id, + 'class': "child", + 'html': html + }); + + li.store("order", link.order); + li.store("lid", link.id); + + li.adopt(div); + ul.adopt(li); + }); + this.sorts = new Sortables(ul, { + constrain: false, + clone: true, + revert: true, + opacity: 0.4, + handle: ".sorthandle", + onComplete: this.saveSort.bind(this) + }); + this.registerLinkEvents(); + this.linksLoaded = true; + indicateFinish(); + this.toggle(); + }, + + registerLinkEvents: function() { + this.ele.getElements('.child').each(function(child) { + var lid = child.get('id').match(/[0-9]+/); + var imgs = child.getElements('.child_secrow img'); + imgs[0].addEvent('click', function(e) { + new Request({ + method: 'get', + url: '/api/deleteFiles/[' + this + "]", + onSuccess: function() { + $('file_' + this).nix() + }.bind(this), + onFailure: indicateFail + }).send(); + }.bind(lid)); + + imgs[1].addEvent('click', function(e) { + new Request({ + method: 'get', + url: '/api/restartFile/' + this, + onSuccess: function() { + var ele = $('file_' + this); + var imgs = ele.getElements("img"); + imgs[0].set("src", "../img/status_queue.png"); + var spans = ele.getElements(".child_status"); + spans[1].set("html", "queued"); + indicateSuccess(); + }.bind(this), + onFailure: indicateFail + }).send(); + }.bind(lid)); + }); + }, + + toggle: function() { + var child = this.ele.getElement('.children'); + if (child.getStyle('display') == "block") { + child.dissolve(); + } else { + if (!this.linksLoaded) { + this.loadLinks(); + } else { + child.reveal(); + } + } + }, + + + deletePackage: function(event) { + indicateLoad(); + new Request({ + method: 'get', + url: '/api/deletePackages/[' + this.id + "]", + onSuccess: function() { + this.ele.nix(); + indicateFinish(); + }.bind(this), + onFailure: indicateFail + }).send(); + //hide_pack(); + event.stop(); + }, + + restartPackage: function(event) { + indicateLoad(); + new Request({ + method: 'get', + url: '/api/restartPackage/' + this.id, + onSuccess: function() { + this.close(); + indicateSuccess(); + }.bind(this), + onFailure: indicateFail + }).send(); + event.stop(); + }, + + close: function() { + var child = this.ele.getElement('.children'); + if (child.getStyle('display') == "block") { + child.dissolve(); + } + var ul = $("sort_children_{id}".substitute({'id': this.id})); + ul.erase("html"); + this.linksLoaded = false; + }, + + movePackage: function(event) { + indicateLoad(); + new Request({ + method: 'get', + url: '/json/move_package/' + ((this.ui.type + 1) % 2) + "/" + this.id, + onSuccess: function() { + this.ele.nix(); + indicateFinish(); + }.bind(this), + onFailure: indicateFail + }).send(); + event.stop(); + }, + + editPackage: function(event) { + $("pack_form").removeEvents("submit"); + $("pack_form").addEvent("submit", this.savePackage.bind(this)); + + $("pack_id").set("value", this.id); + $("pack_name").set("value", this.name.get("text")); + $("pack_folder").set("value", this.folder.get("text")); + $("pack_pws").set("value", this.password.get("text")); + + root.packageBox.open(); + event.stop(); + }, + + savePackage: function(event) { + $("pack_form").send(); + this.name.set("text", $("pack_name").get("value")); + this.folder.set("text", $("pack_folder").get("value")); + this.password.set("text", $("pack_pws").get("value")); + root.packageBox.close(); + event.stop(); + }, + + saveSort: function(ele, copy) { + var order = []; + this.sorts.serialize(function(li, pos) { + if (li == ele && ele.retrieve("order") != pos) { + order.push(ele.retrieve("lid") + "|" + pos) + } + li.store("order", pos) + }); + if (order.length > 0) { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/json/link_order/' + order[0], + onSuccess: indicateFinish, + onFailure: indicateFail + }).send(); + } + } + +}); diff --git a/module/webui/themes/default/js/render/settings.coffee b/module/webui/themes/default/js/render/settings.coffee new file mode 100644 index 000000000..d522741b9 --- /dev/null +++ b/module/webui/themes/default/js/render/settings.coffee @@ -0,0 +1,107 @@ +root = this + +window.addEvent 'domready', -> + root.accountDialog = new MooDialog {destroyOnHide: false} + root.accountDialog.setContent $ 'account_box' + + new TinyTab $$('#toptabs li a'), $$('#tabs-body > span') + + $$('ul.nav').each (nav) -> + new MooDropMenu nav, { + onOpen: (el) -> el.fade 'in' + onClose: (el) -> el.fade 'out' + onInitialize: (el) -> el.fade('hide').set 'tween', {duration:500} + } + + new SettingsUI() + + +class SettingsUI + constructor: -> + @menu = $$ "#general-menu li" + @menu.append $$ "#plugin-menu li" + + @name = $ "tabsback" + @general = $ "general_form_content" + @plugin = $ "plugin_form_content" + + el.addEvent 'click', @menuClick.bind(this) for el in @menu + + $("general|submit").addEvent "click", @configSubmit.bind(this) + $("plugin|submit").addEvent "click", @configSubmit.bind(this) + + $("account_add").addEvent "click", (e) -> + root.accountDialog.open() + e.stop() + + $("account_reset").addEvent "click", (e) -> + root.accountDialog.close() + + $("account_add_button").addEvent "click", @addAccount.bind(this) + $("account_submit").addEvent "click", @submitAccounts.bind(this) + + + menuClick: (e) -> + [category, section] = e.target.get("id").split("|") + name = e.target.get "text" + + + target = if category is "general" then @general else @plugin + target.dissolve() + + new Request({ + "method" : "get" + "url" : "/json/load_config/#{category}/#{section}" + 'onSuccess': (data) => + target.set "html", data + target.reveal() + this.name.set "text", name + }).send() + + + configSubmit: (e) -> + category = e.target.get("id").split("|")[0] + form = $("#{category}_form") + + form.set "send", { + 'method': "post" + 'url': "/json/save_config/#{category}" + "onSuccess" : -> + root.notify.alert '{{ _("Settings saved.")}}', { + 'className': 'success' + } + 'onFailure': -> + root.notify.alert '{{ _("Error occured.")}}', { + 'className': 'error' + } + } + form.send() + e.stop() + + addAccount: (e) -> + form = $ "add_account_form" + form.set "send", { + 'method': "post" + "onSuccess" : -> window.location.reload() + 'onFailure': -> + root.notify.alert '{{_("Error occured.")}}', { + 'className': 'error' + } + } + + form.send() + e.stop() + + submitAccounts: (e) -> + form = $ "account_form" + form.set "send", { + 'method': "post", + "onSuccess" : -> window.location.reload() + 'onFailure': -> + root.notify.alert('{{ _("Error occured.") }}', { + 'className': 'error' + }) + } + + form.send() + e.stop() diff --git a/module/webui/themes/default/js/render/settings.min.js b/module/webui/themes/default/js/render/settings.min.js new file mode 100644 index 000000000..41d1cb25a --- /dev/null +++ b/module/webui/themes/default/js/render/settings.min.js @@ -0,0 +1,3 @@ +{% autoescape true %} +var SettingsUI,root;var __bind=function(a,b){return function(){return a.apply(b,arguments)}};root=this;window.addEvent("domready",function(){root.accountDialog=new MooDialog({destroyOnHide:false});root.accountDialog.setContent($("account_box"));new TinyTab($$("#toptabs li a"),$$("#tabs-body > span"));$$("ul.nav").each(function(a){return new MooDropMenu(a,{onOpen:function(b){return b.fade("in")},onClose:function(b){return b.fade("out")},onInitialize:function(b){return b.fade("hide").set("tween",{duration:500})}})});return new SettingsUI()});SettingsUI=(function(){function a(){var c,e,b,d;this.menu=$$("#general-menu li");this.menu.append($$("#plugin-menu li"));this.name=$("tabsback");this.general=$("general_form_content");this.plugin=$("plugin_form_content");d=this.menu;for(e=0,b=d.length;e<b;e++){c=d[e];c.addEvent("click",this.menuClick.bind(this))}$("general|submit").addEvent("click",this.configSubmit.bind(this));$("plugin|submit").addEvent("click",this.configSubmit.bind(this));$("account_add").addEvent("click",function(f){root.accountDialog.open();return f.stop()});$("account_reset").addEvent("click",function(f){return root.accountDialog.close()});$("account_add_button").addEvent("click",this.addAccount.bind(this));$("account_submit").addEvent("click",this.submitAccounts.bind(this))}a.prototype.menuClick=function(h){var c,b,g,f,d;d=h.target.get("id").split("|"),c=d[0],g=d[1];b=h.target.get("text");f=c==="general"?this.general:this.plugin;f.dissolve();return new Request({method:"get",url:"/json/load_config/"+c+"/"+g,onSuccess:__bind(function(e){f.set("html",e);f.reveal();return this.name.set("text",b)},this)}).send()};a.prototype.configSubmit=function(d){var c,b;c=d.target.get("id").split("|")[0];b=$(""+c+"_form");b.set("send",{method:"post",url:"/json/save_config/"+c,onSuccess:function(){return root.notify.alert('{{ _("Settings saved.")}}',{className:"success"})},onFailure:function(){return root.notify.alert('{{ _("Error occured.")}}',{className:"error"})}});b.send();return d.stop()};a.prototype.addAccount=function(c){var b;b=$("add_account_form");b.set("send",{method:"post",onSuccess:function(){return window.location.reload()},onFailure:function(){return root.notify.alert('{{_("Error occured.")}}',{className:"error"})}});b.send();return c.stop()};a.prototype.submitAccounts=function(c){var b;b=$("account_form");b.set("send",{method:"post",onSuccess:function(){return window.location.reload()},onFailure:function(){return root.notify.alert('{{ _("Error occured.") }}',{className:"error"})}});b.send();return c.stop()};return a})(); +{% endautoescape %} diff --git a/module/webui/themes/default/js/static/MooDialog.js b/module/webui/themes/default/js/static/MooDialog.js new file mode 100644 index 000000000..45a52496f --- /dev/null +++ b/module/webui/themes/default/js/static/MooDialog.js @@ -0,0 +1,140 @@ +/* +--- +name: MooDialog +description: The base class of MooDialog +authors: Arian Stolwijk +license: MIT-style license +requires: [Core/Class, Core/Element, Core/Element.Style, Core/Element.Event] +provides: [MooDialog, Element.MooDialog] +... +*/ + + +var MooDialog = new Class({ + + Implements: [Options, Events], + + options: { + 'class': 'MooDialog', + title: null, + scroll: true, // IE + forceScroll: false, + useEscKey: true, + destroyOnHide: true, + autoOpen: true, + closeButton: true, + onInitialize: function(){ + this.wrapper.setStyle('display', 'none'); + }, + onBeforeOpen: function(){ + this.wrapper.setStyle('display', 'block'); + this.fireEvent('show'); + }, + onBeforeClose: function(){ + this.wrapper.setStyle('display', 'none'); + this.fireEvent('hide'); + }/*, + onOpen: function(){}, + onClose: function(){}, + onShow: function(){}, + onHide: function(){}, + onInitialize: function(wrapper){}, + onContentChange: function(content){}*/ + }, + + initialize: function(options){ + this.setOptions(options); + this.options.inject = this.options.inject || document.body; + options = this.options; + + var wrapper = this.wrapper = new Element('div.' + options['class'].replace(' ', '.')).inject(options.inject); + this.content = new Element('div.content').inject(wrapper); + + if (options.title){ + this.title = new Element('div.title').set('text', options.title).inject(wrapper); + wrapper.addClass('MooDialogTitle'); + } + + if (options.closeButton){ + this.closeButton = new Element('a.close', { + events: {click: this.close.bind(this)} + }).inject(wrapper); + } + + + /*<ie6>*/// IE 6 scroll + if ((options.scroll && Browser.ie6) || options.forceScroll){ + wrapper.setStyle('position', 'absolute'); + var position = wrapper.getPosition(options.inject); + window.addEvent('scroll', function(){ + var scroll = document.getScroll(); + wrapper.setPosition({ + x: position.x + scroll.x, + y: position.y + scroll.y + }); + }); + } + /*</ie6>*/ + + if (options.useEscKey){ + // Add event for the esc key + document.addEvent('keydown', function(e){ + if (e.key == 'esc') this.close(); + }.bind(this)); + } + + this.addEvent('hide', function(){ + if (options.destroyOnHide) this.destroy(); + }.bind(this)); + + this.fireEvent('initialize', wrapper); + }, + + setContent: function(){ + var content = Array.from(arguments); + if (content.length == 1) content = content[0]; + + this.content.empty(); + + var type = typeOf(content); + if (['string', 'number'].contains(type)) this.content.set('text', content); + else this.content.adopt(content); + + this.fireEvent('contentChange', this.content); + + return this; + }, + + open: function(){ + this.fireEvent('beforeOpen', this.wrapper).fireEvent('open'); + this.opened = true; + return this; + }, + + close: function(){ + this.fireEvent('beforeClose', this.wrapper).fireEvent('close'); + this.opened = false; + return this; + }, + + destroy: function(){ + this.wrapper.destroy(); + }, + + toElement: function(){ + return this.wrapper; + } + +}); + + +Element.implement({ + + MooDialog: function(options){ + this.store('MooDialog', + new MooDialog(options).setContent(this).open() + ); + return this; + } + +}); diff --git a/module/webui/themes/default/js/static/MooDialog.min.js b/module/webui/themes/default/js/static/MooDialog.min.js new file mode 100644 index 000000000..90b3ae100 --- /dev/null +++ b/module/webui/themes/default/js/static/MooDialog.min.js @@ -0,0 +1 @@ +var MooDialog=new Class({Implements:[Options,Events],options:{"class":"MooDialog",title:null,scroll:!0,forceScroll:!1,useEscKey:!0,destroyOnHide:!0,autoOpen:!0,closeButton:!0,onInitialize:function(){this.wrapper.setStyle("display","none")},onBeforeOpen:function(){this.wrapper.setStyle("display","block"),this.fireEvent("show")},onBeforeClose:function(){this.wrapper.setStyle("display","none"),this.fireEvent("hide")}},initialize:function(t){this.setOptions(t),this.options.inject=this.options.inject||document.body,t=this.options;var e=this.wrapper=new Element("div."+t["class"].replace(" ",".")).inject(t.inject);if(this.content=new Element("div.content").inject(e),t.title&&(this.title=new Element("div.title").set("text",t.title).inject(e),e.addClass("MooDialogTitle")),t.closeButton&&(this.closeButton=new Element("a.close",{events:{click:this.close.bind(this)}}).inject(e)),t.scroll&&Browser.ie6||t.forceScroll){e.setStyle("position","absolute");var n=e.getPosition(t.inject);window.addEvent("scroll",function(){var t=document.getScroll();e.setPosition({x:n.x+t.x,y:n.y+t.y})})}t.useEscKey&&document.addEvent("keydown",function(t){"esc"==t.key&&this.close()}.bind(this)),this.addEvent("hide",function(){t.destroyOnHide&&this.destroy()}.bind(this)),this.fireEvent("initialize",e)},setContent:function(){var t=Array.from(arguments);1==t.length&&(t=t[0]),this.content.empty();var e=typeOf(t);return["string","number"].contains(e)?this.content.set("text",t):this.content.adopt(t),this.fireEvent("contentChange",this.content),this},open:function(){return this.fireEvent("beforeOpen",this.wrapper).fireEvent("open"),this.opened=!0,this},close:function(){return this.fireEvent("beforeClose",this.wrapper).fireEvent("close"),this.opened=!1,this},destroy:function(){this.wrapper.destroy()},toElement:function(){return this.wrapper}});Element.implement({MooDialog:function(t){return this.store("MooDialog",new MooDialog(t).setContent(this).open()),this}});
\ No newline at end of file diff --git a/module/webui/themes/default/js/static/MooDropMenu.js b/module/webui/themes/default/js/static/MooDropMenu.js new file mode 100644 index 000000000..ac0fa1874 --- /dev/null +++ b/module/webui/themes/default/js/static/MooDropMenu.js @@ -0,0 +1,86 @@ +/* +--- +description: This provides a simple Drop Down menu with infinit levels + +license: MIT-style + +authors: +- Arian Stolwijk + +requires: + - Core/Class.Extras + - Core/Element.Event + - Core/Selectors + +provides: [MooDropMenu, Element.MooDropMenu] + +... +*/ + +var MooDropMenu = new Class({ + + Implements: [Options, Events], + + options: { + onOpen: function(el){ + el.removeClass('close').addClass('open'); + }, + onClose: function(el){ + el.removeClass('open').addClass('close'); + }, + onInitialize: function(el){ + el.removeClass('open').addClass('close'); + }, + mouseoutDelay: 200, + mouseoverDelay: 0, + listSelector: 'ul', + itemSelector: 'li', + openEvent: 'mouseenter', + closeEvent: 'mouseleave' + }, + + initialize: function(menu, options, level){ + this.setOptions(options); + options = this.options; + + var menu = this.menu = document.id(menu); + + menu.getElements(options.itemSelector + ' > ' + options.listSelector).each(function(el){ + + this.fireEvent('initialize', el); + + var parent = el.getParent(options.itemSelector), + timer; + + parent.addEvent(options.openEvent, function(){ + parent.store('DropDownOpen', true); + + clearTimeout(timer); + if (options.mouseoverDelay) timer = this.fireEvent.delay(options.mouseoverDelay, this, ['open', el]); + else this.fireEvent('open', el); + + }.bind(this)).addEvent(options.closeEvent, function(){ + parent.store('DropDownOpen', false); + + clearTimeout(timer); + timer = (function(){ + if (!parent.retrieve('DropDownOpen')) this.fireEvent('close', el); + }).delay(options.mouseoutDelay, this); + + }.bind(this)); + + }, this); + }, + + toElement: function(){ + return this.menu + } + +}); + +/* So you can do like this $('nav').MooDropMenu(); or even $('nav').MooDropMenu().setStyle('border',1); */ +Element.implement({ + MooDropMenu: function(options){ + return this.store('MooDropMenu', new MooDropMenu(this, options)); + } +}); diff --git a/module/webui/themes/default/js/static/MooDropMenu.min.js b/module/webui/themes/default/js/static/MooDropMenu.min.js new file mode 100644 index 000000000..552ae247a --- /dev/null +++ b/module/webui/themes/default/js/static/MooDropMenu.min.js @@ -0,0 +1 @@ +var MooDropMenu=new Class({Implements:[Options,Events],options:{onOpen:function(e){e.removeClass("close").addClass("open")},onClose:function(e){e.removeClass("open").addClass("close")},onInitialize:function(e){e.removeClass("open").addClass("close")},mouseoutDelay:200,mouseoverDelay:0,listSelector:"ul",itemSelector:"li",openEvent:"mouseenter",closeEvent:"mouseleave"},initialize:function(e,o){this.setOptions(o),o=this.options;var e=this.menu=document.id(e);e.getElements(o.itemSelector+" > "+o.listSelector).each(function(e){this.fireEvent("initialize",e);var n,t=e.getParent(o.itemSelector);t.addEvent(o.openEvent,function(){t.store("DropDownOpen",!0),clearTimeout(n),o.mouseoverDelay?n=this.fireEvent.delay(o.mouseoverDelay,this,["open",e]):this.fireEvent("open",e)}.bind(this)).addEvent(o.closeEvent,function(){t.store("DropDownOpen",!1),clearTimeout(n),n=function(){t.retrieve("DropDownOpen")||this.fireEvent("close",e)}.delay(o.mouseoutDelay,this)}.bind(this))},this)},toElement:function(){return this.menu}});Element.implement({MooDropMenu:function(e){return this.store("MooDropMenu",new MooDropMenu(this,e))}});
\ No newline at end of file diff --git a/module/webui/themes/default/js/static/mootools-core.js b/module/webui/themes/default/js/static/mootools-core.js new file mode 100644 index 000000000..db83850fd --- /dev/null +++ b/module/webui/themes/default/js/static/mootools-core.js @@ -0,0 +1,5977 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/core/8423c12ffd6a6bfcde9ea22554aec795 + +packager build: + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady + +... +*/ + +/* +--- + +name: Core + +description: The heart of MooTools. + +license: MIT-style license. + +copyright: Copyright (c) 2006-2014 [Valerio Proietti](http://mad4milk.net/). + +authors: The MooTools production team (http://mootools.net/developers/) + +inspiration: + - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) + - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) + +provides: [Core, MooTools, Type, typeOf, instanceOf, Native] + +... +*/ + +(function(){ + +this.MooTools = { + version: '1.5.0', + build: '0f7b690afee9349b15909f33016a25d2e4d9f4e3' +}; + +// typeOf, instanceOf + +var typeOf = this.typeOf = function(item){ + if (item == null) return 'null'; + if (item.$family != null) return item.$family(); + + if (item.nodeName){ + if (item.nodeType == 1) return 'element'; + if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; + } else if (typeof item.length == 'number'){ + if ('callee' in item) return 'arguments'; + if ('item' in item) return 'collection'; + } + + return typeof item; +}; + +var instanceOf = this.instanceOf = function(item, object){ + if (item == null) return false; + var constructor = item.$constructor || item.constructor; + while (constructor){ + if (constructor === object) return true; + constructor = constructor.parent; + } + /*<ltIE8>*/ + if (!item.hasOwnProperty) return false; + /*</ltIE8>*/ + return item instanceof object; +}; + +// Function overloading + +var Function = this.Function; + +var enumerables = true; +for (var i in {toString: 1}) enumerables = null; +if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; + +Function.prototype.overloadSetter = function(usePlural){ + var self = this; + return function(a, b){ + if (a == null) return this; + if (usePlural || typeof a != 'string'){ + for (var k in a) self.call(this, k, a[k]); + if (enumerables) for (var i = enumerables.length; i--;){ + k = enumerables[i]; + if (a.hasOwnProperty(k)) self.call(this, k, a[k]); + } + } else { + self.call(this, a, b); + } + return this; + }; +}; + +Function.prototype.overloadGetter = function(usePlural){ + var self = this; + return function(a){ + var args, result; + if (typeof a != 'string') args = a; + else if (arguments.length > 1) args = arguments; + else if (usePlural) args = [a]; + if (args){ + result = {}; + for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); + } else { + result = self.call(this, a); + } + return result; + }; +}; + +Function.prototype.extend = function(key, value){ + this[key] = value; +}.overloadSetter(); + +Function.prototype.implement = function(key, value){ + this.prototype[key] = value; +}.overloadSetter(); + +// From + +var slice = Array.prototype.slice; + +Function.from = function(item){ + return (typeOf(item) == 'function') ? item : function(){ + return item; + }; +}; + +Array.from = function(item){ + if (item == null) return []; + return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; +}; + +Number.from = function(item){ + var number = parseFloat(item); + return isFinite(number) ? number : null; +}; + +String.from = function(item){ + return item + ''; +}; + +// hide, protect + +Function.implement({ + + hide: function(){ + this.$hidden = true; + return this; + }, + + protect: function(){ + this.$protected = true; + return this; + } + +}); + +// Type + +var Type = this.Type = function(name, object){ + if (name){ + var lower = name.toLowerCase(); + var typeCheck = function(item){ + return (typeOf(item) == lower); + }; + + Type['is' + name] = typeCheck; + if (object != null){ + object.prototype.$family = (function(){ + return lower; + }).hide(); + + } + } + + if (object == null) return null; + + object.extend(this); + object.$constructor = Type; + object.prototype.$constructor = object; + + return object; +}; + +var toString = Object.prototype.toString; + +Type.isEnumerable = function(item){ + return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); +}; + +var hooks = {}; + +var hooksOf = function(object){ + var type = typeOf(object.prototype); + return hooks[type] || (hooks[type] = []); +}; + +var implement = function(name, method){ + if (method && method.$hidden) return; + + var hooks = hooksOf(this); + + for (var i = 0; i < hooks.length; i++){ + var hook = hooks[i]; + if (typeOf(hook) == 'type') implement.call(hook, name, method); + else hook.call(this, name, method); + } + + var previous = this.prototype[name]; + if (previous == null || !previous.$protected) this.prototype[name] = method; + + if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ + return method.apply(item, slice.call(arguments, 1)); + }); +}; + +var extend = function(name, method){ + if (method && method.$hidden) return; + var previous = this[name]; + if (previous == null || !previous.$protected) this[name] = method; +}; + +Type.implement({ + + implement: implement.overloadSetter(), + + extend: extend.overloadSetter(), + + alias: function(name, existing){ + implement.call(this, name, this.prototype[existing]); + }.overloadSetter(), + + mirror: function(hook){ + hooksOf(this).push(hook); + return this; + } + +}); + +new Type('Type', Type); + +// Default Types + +var force = function(name, object, methods){ + var isType = (object != Object), + prototype = object.prototype; + + if (isType) object = new Type(name, object); + + for (var i = 0, l = methods.length; i < l; i++){ + var key = methods[i], + generic = object[key], + proto = prototype[key]; + + if (generic) generic.protect(); + if (isType && proto) object.implement(key, proto.protect()); + } + + if (isType){ + var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]); + object.forEachMethod = function(fn){ + if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){ + fn.call(prototype, prototype[methods[i]], methods[i]); + } + for (var key in prototype) fn.call(prototype, prototype[key], key); + }; + } + + return force; +}; + +force('String', String, [ + 'charAt', 'charCodeAt', 'concat', 'contains', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', + 'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase' +])('Array', Array, [ + 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', + 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' +])('Number', Number, [ + 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' +])('Function', Function, [ + 'apply', 'call', 'bind' +])('RegExp', RegExp, [ + 'exec', 'test' +])('Object', Object, [ + 'create', 'defineProperty', 'defineProperties', 'keys', + 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', + 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' +])('Date', Date, ['now']); + +Object.extend = extend.overloadSetter(); + +Date.extend('now', function(){ + return +(new Date); +}); + +new Type('Boolean', Boolean); + +// fixes NaN returning as Number + +Number.prototype.$family = function(){ + return isFinite(this) ? 'number' : 'null'; +}.hide(); + +// Number.random + +Number.extend('random', function(min, max){ + return Math.floor(Math.random() * (max - min + 1) + min); +}); + +// forEach, each + +var hasOwnProperty = Object.prototype.hasOwnProperty; +Object.extend('forEach', function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); + } +}); + +Object.each = Object.forEach; + +Array.implement({ + + /*<!ES5>*/ + forEach: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) fn.call(bind, this[i], i, this); + } + }, + /*</!ES5>*/ + + each: function(fn, bind){ + Array.forEach(this, fn, bind); + return this; + } + +}); + +// Array & Object cloning, Object merging and appending + +var cloneOf = function(item){ + switch (typeOf(item)){ + case 'array': return item.clone(); + case 'object': return Object.clone(item); + default: return item; + } +}; + +Array.implement('clone', function(){ + var i = this.length, clone = new Array(i); + while (i--) clone[i] = cloneOf(this[i]); + return clone; +}); + +var mergeOne = function(source, key, current){ + switch (typeOf(current)){ + case 'object': + if (typeOf(source[key]) == 'object') Object.merge(source[key], current); + else source[key] = Object.clone(current); + break; + case 'array': source[key] = current.clone(); break; + default: source[key] = current; + } + return source; +}; + +Object.extend({ + + merge: function(source, k, v){ + if (typeOf(k) == 'string') return mergeOne(source, k, v); + for (var i = 1, l = arguments.length; i < l; i++){ + var object = arguments[i]; + for (var key in object) mergeOne(source, key, object[key]); + } + return source; + }, + + clone: function(object){ + var clone = {}; + for (var key in object) clone[key] = cloneOf(object[key]); + return clone; + }, + + append: function(original){ + for (var i = 1, l = arguments.length; i < l; i++){ + var extended = arguments[i] || {}; + for (var key in extended) original[key] = extended[key]; + } + return original; + } + +}); + +// Object-less types + +['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ + new Type(name); +}); + +// Unique ID + +var UID = Date.now(); + +String.extend('uniqueID', function(){ + return (UID++).toString(36); +}); + + + +})(); + + +/* +--- + +name: Array + +description: Contains Array Prototypes like each, contains, and erase. + +license: MIT-style license. + +requires: [Type] + +provides: Array + +... +*/ + +Array.implement({ + + /*<!ES5>*/ + every: function(fn, bind){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ + if ((i in this) && !fn.call(bind, this[i], i, this)) return false; + } + return true; + }, + + filter: function(fn, bind){ + var results = []; + for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){ + value = this[i]; + if (fn.call(bind, value, i, this)) results.push(value); + } + return results; + }, + + indexOf: function(item, from){ + var length = this.length >>> 0; + for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){ + if (this[i] === item) return i; + } + return -1; + }, + + map: function(fn, bind){ + var length = this.length >>> 0, results = Array(length); + for (var i = 0; i < length; i++){ + if (i in this) results[i] = fn.call(bind, this[i], i, this); + } + return results; + }, + + some: function(fn, bind){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ + if ((i in this) && fn.call(bind, this[i], i, this)) return true; + } + return false; + }, + /*</!ES5>*/ + + clean: function(){ + return this.filter(function(item){ + return item != null; + }); + }, + + invoke: function(methodName){ + var args = Array.slice(arguments, 1); + return this.map(function(item){ + return item[methodName].apply(item, args); + }); + }, + + associate: function(keys){ + var obj = {}, length = Math.min(this.length, keys.length); + for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; + return obj; + }, + + link: function(object){ + var result = {}; + for (var i = 0, l = this.length; i < l; i++){ + for (var key in object){ + if (object[key](this[i])){ + result[key] = this[i]; + delete object[key]; + break; + } + } + } + return result; + }, + + contains: function(item, from){ + return this.indexOf(item, from) != -1; + }, + + append: function(array){ + this.push.apply(this, array); + return this; + }, + + getLast: function(){ + return (this.length) ? this[this.length - 1] : null; + }, + + getRandom: function(){ + return (this.length) ? this[Number.random(0, this.length - 1)] : null; + }, + + include: function(item){ + if (!this.contains(item)) this.push(item); + return this; + }, + + combine: function(array){ + for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); + return this; + }, + + erase: function(item){ + for (var i = this.length; i--;){ + if (this[i] === item) this.splice(i, 1); + } + return this; + }, + + empty: function(){ + this.length = 0; + return this; + }, + + flatten: function(){ + var array = []; + for (var i = 0, l = this.length; i < l; i++){ + var type = typeOf(this[i]); + if (type == 'null') continue; + array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); + } + return array; + }, + + pick: function(){ + for (var i = 0, l = this.length; i < l; i++){ + if (this[i] != null) return this[i]; + } + return null; + }, + + hexToRgb: function(array){ + if (this.length != 3) return null; + var rgb = this.map(function(value){ + if (value.length == 1) value += value; + return parseInt(value, 16); + }); + return (array) ? rgb : 'rgb(' + rgb + ')'; + }, + + rgbToHex: function(array){ + if (this.length < 3) return null; + if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; + var hex = []; + for (var i = 0; i < 3; i++){ + var bit = (this[i] - 0).toString(16); + hex.push((bit.length == 1) ? '0' + bit : bit); + } + return (array) ? hex : '#' + hex.join(''); + } + +}); + + + + +/* +--- + +name: String + +description: Contains String Prototypes like camelCase, capitalize, test, and toInt. + +license: MIT-style license. + +requires: [Type, Array] + +provides: String + +... +*/ + +String.implement({ + + //<!ES6> + contains: function(string, index){ + return (index ? String(this).slice(index) : String(this)).indexOf(string) > -1; + }, + //</!ES6> + + test: function(regex, params){ + return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); + }, + + trim: function(){ + return String(this).replace(/^\s+|\s+$/g, ''); + }, + + clean: function(){ + return String(this).replace(/\s+/g, ' ').trim(); + }, + + camelCase: function(){ + return String(this).replace(/-\D/g, function(match){ + return match.charAt(1).toUpperCase(); + }); + }, + + hyphenate: function(){ + return String(this).replace(/[A-Z]/g, function(match){ + return ('-' + match.charAt(0).toLowerCase()); + }); + }, + + capitalize: function(){ + return String(this).replace(/\b[a-z]/g, function(match){ + return match.toUpperCase(); + }); + }, + + escapeRegExp: function(){ + return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + hexToRgb: function(array){ + var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); + return (hex) ? hex.slice(1).hexToRgb(array) : null; + }, + + rgbToHex: function(array){ + var rgb = String(this).match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHex(array) : null; + }, + + substitute: function(object, regexp){ + return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ + if (match.charAt(0) == '\\') return match.slice(1); + return (object[name] != null) ? object[name] : ''; + }); + } + +}); + + + + +/* +--- + +name: Number + +description: Contains Number Prototypes like limit, round, times, and ceil. + +license: MIT-style license. + +requires: Type + +provides: Number + +... +*/ + +Number.implement({ + + limit: function(min, max){ + return Math.min(max, Math.max(min, this)); + }, + + round: function(precision){ + precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); + return Math.round(this * precision) / precision; + }, + + times: function(fn, bind){ + for (var i = 0; i < this; i++) fn.call(bind, i, this); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + } + +}); + +Number.alias('each', 'times'); + +(function(math){ + var methods = {}; + math.each(function(name){ + if (!Number[name]) methods[name] = function(){ + return Math[name].apply(null, [this].concat(Array.from(arguments))); + }; + }); + Number.implement(methods); +})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); + + +/* +--- + +name: Function + +description: Contains Function Prototypes like create, bind, pass, and delay. + +license: MIT-style license. + +requires: Type + +provides: Function + +... +*/ + +Function.extend({ + + attempt: function(){ + for (var i = 0, l = arguments.length; i < l; i++){ + try { + return arguments[i](); + } catch (e){} + } + return null; + } + +}); + +Function.implement({ + + attempt: function(args, bind){ + try { + return this.apply(bind, Array.from(args)); + } catch (e){} + + return null; + }, + + /*<!ES5-bind>*/ + bind: function(that){ + var self = this, + args = arguments.length > 1 ? Array.slice(arguments, 1) : null, + F = function(){}; + + var bound = function(){ + var context = that, length = arguments.length; + if (this instanceof bound){ + F.prototype = self.prototype; + context = new F; + } + var result = (!args && !length) + ? self.call(context) + : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments); + return context == that ? result : context; + }; + return bound; + }, + /*</!ES5-bind>*/ + + pass: function(args, bind){ + var self = this; + if (args != null) args = Array.from(args); + return function(){ + return self.apply(bind, args || arguments); + }; + }, + + delay: function(delay, bind, args){ + return setTimeout(this.pass((args == null ? [] : args), bind), delay); + }, + + periodical: function(periodical, bind, args){ + return setInterval(this.pass((args == null ? [] : args), bind), periodical); + } + +}); + + + + +/* +--- + +name: Object + +description: Object generic methods + +license: MIT-style license. + +requires: Type + +provides: [Object, Hash] + +... +*/ + +(function(){ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +Object.extend({ + + subset: function(object, keys){ + var results = {}; + for (var i = 0, l = keys.length; i < l; i++){ + var k = keys[i]; + if (k in object) results[k] = object[k]; + } + return results; + }, + + map: function(object, fn, bind){ + var results = {}; + for (var key in object){ + if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object); + } + return results; + }, + + filter: function(object, fn, bind){ + var results = {}; + for (var key in object){ + var value = object[key]; + if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value; + } + return results; + }, + + every: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false; + } + return true; + }, + + some: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true; + } + return false; + }, + + keys: function(object){ + var keys = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) keys.push(key); + } + return keys; + }, + + values: function(object){ + var values = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) values.push(object[key]); + } + return values; + }, + + getLength: function(object){ + return Object.keys(object).length; + }, + + keyOf: function(object, value){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && object[key] === value) return key; + } + return null; + }, + + contains: function(object, value){ + return Object.keyOf(object, value) != null; + }, + + toQueryString: function(object, base){ + var queryString = []; + + Object.each(object, function(value, key){ + if (base) key = base + '[' + key + ']'; + var result; + switch (typeOf(value)){ + case 'object': result = Object.toQueryString(value, key); break; + case 'array': + var qs = {}; + value.each(function(val, i){ + qs[i] = val; + }); + result = Object.toQueryString(qs, key); + break; + default: result = key + '=' + encodeURIComponent(value); + } + if (value != null) queryString.push(result); + }); + + return queryString.join('&'); + } + +}); + +})(); + + + + +/* +--- + +name: Browser + +description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. + +license: MIT-style license. + +requires: [Array, Function, Number, String] + +provides: [Browser, Window, Document] + +... +*/ + +(function(){ + +var document = this.document; +var window = document.window = this; + +var parse = function(ua, platform){ + ua = ua.toLowerCase(); + platform = (platform ? platform.toLowerCase() : ''); + + var UA = ua.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/) || [null, 'unknown', 0]; + + if (UA[1] == 'trident'){ + UA[1] = 'ie'; + if (UA[4]) UA[2] = UA[4]; + } else if (UA[1] == 'crios') { + UA[1] = 'chrome'; + } + + var platform = ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]; + if (platform == 'win') platform = 'windows'; + + return { + extend: Function.prototype.extend, + name: (UA[1] == 'version') ? UA[3] : UA[1], + version: parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), + platform: platform + }; +}; + +var Browser = this.Browser = parse(navigator.userAgent, navigator.platform); + +if (Browser.ie){ + Browser.version = document.documentMode; +} + +Browser.extend({ + Features: { + xpath: !!(document.evaluate), + air: !!(window.runtime), + query: !!(document.querySelector), + json: !!(window.JSON) + }, + parseUA: parse +}); + + + +// Request + +Browser.Request = (function(){ + + var XMLHTTP = function(){ + return new XMLHttpRequest(); + }; + + var MSXML2 = function(){ + return new ActiveXObject('MSXML2.XMLHTTP'); + }; + + var MSXML = function(){ + return new ActiveXObject('Microsoft.XMLHTTP'); + }; + + return Function.attempt(function(){ + XMLHTTP(); + return XMLHTTP; + }, function(){ + MSXML2(); + return MSXML2; + }, function(){ + MSXML(); + return MSXML; + }); + +})(); + +Browser.Features.xhr = !!(Browser.Request); + + + +// String scripts + +Browser.exec = function(text){ + if (!text) return text; + if (window.execScript){ + window.execScript(text); + } else { + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.text = text; + document.head.appendChild(script); + document.head.removeChild(script); + } + return text; +}; + +String.implement('stripScripts', function(exec){ + var scripts = ''; + var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){ + scripts += code + '\n'; + return ''; + }); + if (exec === true) Browser.exec(scripts); + else if (typeOf(exec) == 'function') exec(scripts, text); + return text; +}); + +// Window, Document + +Browser.extend({ + Document: this.Document, + Window: this.Window, + Element: this.Element, + Event: this.Event +}); + +this.Window = this.$constructor = new Type('Window', function(){}); + +this.$family = Function.from('window').hide(); + +Window.mirror(function(name, method){ + window[name] = method; +}); + +this.Document = document.$constructor = new Type('Document', function(){}); + +document.$family = Function.from('document').hide(); + +Document.mirror(function(name, method){ + document[name] = method; +}); + +document.html = document.documentElement; +if (!document.head) document.head = document.getElementsByTagName('head')[0]; + +if (document.execCommand) try { + document.execCommand("BackgroundImageCache", false, true); +} catch (e){} + +/*<ltIE9>*/ +if (this.attachEvent && !this.addEventListener){ + var unloadEvent = function(){ + this.detachEvent('onunload', unloadEvent); + document.head = document.html = document.window = null; + }; + this.attachEvent('onunload', unloadEvent); +} + +// IE fails on collections and <select>.options (refers to <select>) +var arrayFrom = Array.from; +try { + arrayFrom(document.html.childNodes); +} catch(e){ + Array.from = function(item){ + if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ + var i = item.length, array = new Array(i); + while (i--) array[i] = item[i]; + return array; + } + return arrayFrom(item); + }; + + var prototype = Array.prototype, + slice = prototype.slice; + ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ + var method = prototype[name]; + Array[name] = function(item){ + return method.apply(Array.from(item), slice.call(arguments, 1)); + }; + }); +} +/*</ltIE9>*/ + + + +})(); + + +/* +--- + +name: Event + +description: Contains the Event Type, to make the event object cross-browser. + +license: MIT-style license. + +requires: [Window, Document, Array, Function, String, Object] + +provides: Event + +... +*/ + +(function() { + +var _keys = {}; + +var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){ + if (!win) win = window; + event = event || win.event; + if (event.$extended) return event; + this.event = event; + this.$extended = true; + this.shift = event.shiftKey; + this.control = event.ctrlKey; + this.alt = event.altKey; + this.meta = event.metaKey; + var type = this.type = event.type; + var target = event.target || event.srcElement; + while (target && target.nodeType == 3) target = target.parentNode; + this.target = document.id(target); + + if (type.indexOf('key') == 0){ + var code = this.code = (event.which || event.keyCode); + this.key = _keys[code]; + if (type == 'keydown' || type == 'keyup'){ + if (code > 111 && code < 124) this.key = 'f' + (code - 111); + else if (code > 95 && code < 106) this.key = code - 96; + } + if (this.key == null) this.key = String.fromCharCode(code).toLowerCase(); + } else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){ + var doc = win.document; + doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; + this.page = { + x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, + y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop + }; + this.client = { + x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, + y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY + }; + if (type == 'DOMMouseScroll' || type == 'mousewheel') + this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; + + this.rightClick = (event.which == 3 || event.button == 2); + if (type == 'mouseover' || type == 'mouseout'){ + var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; + while (related && related.nodeType == 3) related = related.parentNode; + this.relatedTarget = document.id(related); + } + } else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){ + this.rotation = event.rotation; + this.scale = event.scale; + this.targetTouches = event.targetTouches; + this.changedTouches = event.changedTouches; + var touches = this.touches = event.touches; + if (touches && touches[0]){ + var touch = touches[0]; + this.page = {x: touch.pageX, y: touch.pageY}; + this.client = {x: touch.clientX, y: touch.clientY}; + } + } + + if (!this.client) this.client = {}; + if (!this.page) this.page = {}; +}); + +DOMEvent.implement({ + + stop: function(){ + return this.preventDefault().stopPropagation(); + }, + + stopPropagation: function(){ + if (this.event.stopPropagation) this.event.stopPropagation(); + else this.event.cancelBubble = true; + return this; + }, + + preventDefault: function(){ + if (this.event.preventDefault) this.event.preventDefault(); + else this.event.returnValue = false; + return this; + } + +}); + +DOMEvent.defineKey = function(code, key){ + _keys[code] = key; + return this; +}; + +DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true); + +DOMEvent.defineKeys({ + '38': 'up', '40': 'down', '37': 'left', '39': 'right', + '27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab', + '46': 'delete', '13': 'enter' +}); + +})(); + + + + + + +/* +--- + +name: Class + +description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. + +license: MIT-style license. + +requires: [Array, String, Function, Number] + +provides: Class + +... +*/ + +(function(){ + +var Class = this.Class = new Type('Class', function(params){ + if (instanceOf(params, Function)) params = {initialize: params}; + + var newClass = function(){ + reset(this); + if (newClass.$prototyping) return this; + this.$caller = null; + var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; + this.$caller = this.caller = null; + return value; + }.extend(this).implement(params); + + newClass.$constructor = Class; + newClass.prototype.$constructor = newClass; + newClass.prototype.parent = parent; + + return newClass; +}); + +var parent = function(){ + if (!this.$caller) throw new Error('The method "parent" cannot be called.'); + var name = this.$caller.$name, + parent = this.$caller.$owner.parent, + previous = (parent) ? parent.prototype[name] : null; + if (!previous) throw new Error('The method "' + name + '" has no parent.'); + return previous.apply(this, arguments); +}; + +var reset = function(object){ + for (var key in object){ + var value = object[key]; + switch (typeOf(value)){ + case 'object': + var F = function(){}; + F.prototype = value; + object[key] = reset(new F); + break; + case 'array': object[key] = value.clone(); break; + } + } + return object; +}; + +var wrap = function(self, key, method){ + if (method.$origin) method = method.$origin; + var wrapper = function(){ + if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); + var caller = this.caller, current = this.$caller; + this.caller = current; this.$caller = wrapper; + var result = method.apply(this, arguments); + this.$caller = current; this.caller = caller; + return result; + }.extend({$owner: self, $origin: method, $name: key}); + return wrapper; +}; + +var implement = function(key, value, retain){ + if (Class.Mutators.hasOwnProperty(key)){ + value = Class.Mutators[key].call(this, value); + if (value == null) return this; + } + + if (typeOf(value) == 'function'){ + if (value.$hidden) return this; + this.prototype[key] = (retain) ? value : wrap(this, key, value); + } else { + Object.merge(this.prototype, key, value); + } + + return this; +}; + +var getInstance = function(klass){ + klass.$prototyping = true; + var proto = new klass; + delete klass.$prototyping; + return proto; +}; + +Class.implement('implement', implement.overloadSetter()); + +Class.Mutators = { + + Extends: function(parent){ + this.parent = parent; + this.prototype = getInstance(parent); + }, + + Implements: function(items){ + Array.from(items).each(function(item){ + var instance = new item; + for (var key in instance) implement.call(this, key, instance[key], true); + }, this); + } +}; + +})(); + + +/* +--- + +name: Class.Extras + +description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. + +license: MIT-style license. + +requires: Class + +provides: [Class.Extras, Chain, Events, Options] + +... +*/ + +(function(){ + +this.Chain = new Class({ + + $chain: [], + + chain: function(){ + this.$chain.append(Array.flatten(arguments)); + return this; + }, + + callChain: function(){ + return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; + }, + + clearChain: function(){ + this.$chain.empty(); + return this; + } + +}); + +var removeOn = function(string){ + return string.replace(/^on([A-Z])/, function(full, first){ + return first.toLowerCase(); + }); +}; + +this.Events = new Class({ + + $events: {}, + + addEvent: function(type, fn, internal){ + type = removeOn(type); + + + + this.$events[type] = (this.$events[type] || []).include(fn); + if (internal) fn.internal = true; + return this; + }, + + addEvents: function(events){ + for (var type in events) this.addEvent(type, events[type]); + return this; + }, + + fireEvent: function(type, args, delay){ + type = removeOn(type); + var events = this.$events[type]; + if (!events) return this; + args = Array.from(args); + events.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + removeEvent: function(type, fn){ + type = removeOn(type); + var events = this.$events[type]; + if (events && !fn.internal){ + var index = events.indexOf(fn); + if (index != -1) delete events[index]; + } + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + if (events) events = removeOn(events); + for (type in this.$events){ + if (events && events != type) continue; + var fns = this.$events[type]; + for (var i = fns.length; i--;) if (i in fns){ + this.removeEvent(type, fns[i]); + } + } + return this; + } + +}); + +this.Options = new Class({ + + setOptions: function(){ + var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments)); + if (this.addEvent) for (var option in options){ + if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; + this.addEvent(option, options[option]); + delete options[option]; + } + return this; + } + +}); + +})(); + + +/* +--- +name: Slick.Parser +description: Standalone CSS3 Selector parser +provides: Slick.Parser +... +*/ + +;(function(){ + +var parsed, + separatorIndex, + combinatorIndex, + reversed, + cache = {}, + reverseCache = {}, + reUnescape = /\\/g; + +var parse = function(expression, isReversed){ + if (expression == null) return null; + if (expression.Slick === true) return expression; + expression = ('' + expression).replace(/^\s+|\s+$/g, ''); + reversed = !!isReversed; + var currentCache = (reversed) ? reverseCache : cache; + if (currentCache[expression]) return currentCache[expression]; + parsed = { + Slick: true, + expressions: [], + raw: expression, + reverse: function(){ + return parse(this.raw, true); + } + }; + separatorIndex = -1; + while (expression != (expression = expression.replace(regexp, parser))); + parsed.length = parsed.expressions.length; + return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed; +}; + +var reverseCombinator = function(combinator){ + if (combinator === '!') return ' '; + else if (combinator === ' ') return '!'; + else if ((/^!/).test(combinator)) return combinator.replace(/^!/, ''); + else return '!' + combinator; +}; + +var reverse = function(expression){ + var expressions = expression.expressions; + for (var i = 0; i < expressions.length; i++){ + var exp = expressions[i]; + var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)}; + + for (var j = 0; j < exp.length; j++){ + var cexp = exp[j]; + if (!cexp.reverseCombinator) cexp.reverseCombinator = ' '; + cexp.combinator = cexp.reverseCombinator; + delete cexp.reverseCombinator; + } + + exp.reverse().push(last); + } + return expression; +}; + +var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License + return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){ + return '\\' + match; + }); +}; + +var regexp = new RegExp( +/* +#!/usr/bin/env ruby +puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'') +__END__ + "(?x)^(?:\ + \\s* ( , ) \\s* # Separator \n\ + | \\s* ( <combinator>+ ) \\s* # Combinator \n\ + | ( \\s+ ) # CombinatorChildren \n\ + | ( <unicode>+ | \\* ) # Tag \n\ + | \\# ( <unicode>+ ) # ID \n\ + | \\. ( <unicode>+ ) # ClassName \n\ + | # Attribute \n\ + \\[ \ + \\s* (<unicode1>+) (?: \ + \\s* ([*^$!~|]?=) (?: \ + \\s* (?:\ + ([\"']?)(.*?)\\9 \ + )\ + ) \ + )? \\s* \ + \\](?!\\]) \n\ + | :+ ( <unicode>+ )(?:\ + \\( (?:\ + (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\ + ) \\)\ + )?\ + )" +*/ + "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)" + .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']') + .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') + .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') +); + +function parser( + rawMatch, + + separator, + combinator, + combinatorChildren, + + tagName, + id, + className, + + attributeKey, + attributeOperator, + attributeQuote, + attributeValue, + + pseudoMarker, + pseudoClass, + pseudoQuote, + pseudoClassQuotedValue, + pseudoClassValue +){ + if (separator || separatorIndex === -1){ + parsed.expressions[++separatorIndex] = []; + combinatorIndex = -1; + if (separator) return ''; + } + + if (combinator || combinatorChildren || combinatorIndex === -1){ + combinator = combinator || ' '; + var currentSeparator = parsed.expressions[separatorIndex]; + if (reversed && currentSeparator[combinatorIndex]) + currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator); + currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'}; + } + + var currentParsed = parsed.expressions[separatorIndex][combinatorIndex]; + + if (tagName){ + currentParsed.tag = tagName.replace(reUnescape, ''); + + } else if (id){ + currentParsed.id = id.replace(reUnescape, ''); + + } else if (className){ + className = className.replace(reUnescape, ''); + + if (!currentParsed.classList) currentParsed.classList = []; + if (!currentParsed.classes) currentParsed.classes = []; + currentParsed.classList.push(className); + currentParsed.classes.push({ + value: className, + regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') + }); + + } else if (pseudoClass){ + pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue; + pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null; + + if (!currentParsed.pseudos) currentParsed.pseudos = []; + currentParsed.pseudos.push({ + key: pseudoClass.replace(reUnescape, ''), + value: pseudoClassValue, + type: pseudoMarker.length == 1 ? 'class' : 'element' + }); + + } else if (attributeKey){ + attributeKey = attributeKey.replace(reUnescape, ''); + attributeValue = (attributeValue || '').replace(reUnescape, ''); + + var test, regexp; + + switch (attributeOperator){ + case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break; + case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break; + case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break; + case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break; + case '=' : test = function(value){ + return attributeValue == value; + }; break; + case '*=' : test = function(value){ + return value && value.indexOf(attributeValue) > -1; + }; break; + case '!=' : test = function(value){ + return attributeValue != value; + }; break; + default : test = function(value){ + return !!value; + }; + } + + if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){ + return false; + }; + + if (!test) test = function(value){ + return value && regexp.test(value); + }; + + if (!currentParsed.attributes) currentParsed.attributes = []; + currentParsed.attributes.push({ + key: attributeKey, + operator: attributeOperator, + value: attributeValue, + test: test + }); + + } + + return ''; +}; + +// Slick NS + +var Slick = (this.Slick || {}); + +Slick.parse = function(expression){ + return parse(expression); +}; + +Slick.escapeRegExp = escapeRegExp; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); + + +/* +--- +name: Slick.Finder +description: The new, superfast css selector engine. +provides: Slick.Finder +requires: Slick.Parser +... +*/ + +;(function(){ + +var local = {}, + featuresCache = {}, + toString = Object.prototype.toString; + +// Feature / Bug detection + +local.isNativeCode = function(fn){ + return (/\{\s*\[native code\]\s*\}/).test('' + fn); +}; + +local.isXML = function(document){ + return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') || + (document.nodeType == 9 && document.documentElement.nodeName != 'HTML'); +}; + +local.setDocument = function(document){ + + // convert elements / window arguments to document. if document cannot be extrapolated, the function returns. + var nodeType = document.nodeType; + if (nodeType == 9); // document + else if (nodeType) document = document.ownerDocument; // node + else if (document.navigator) document = document.document; // window + else return; + + // check if it's the old document + + if (this.document === document) return; + this.document = document; + + // check if we have done feature detection on this document before + + var root = document.documentElement, + rootUid = this.getUIDXML(root), + features = featuresCache[rootUid], + feature; + + if (features){ + for (feature in features){ + this[feature] = features[feature]; + } + return; + } + + features = featuresCache[rootUid] = {}; + + features.root = root; + features.isXMLDocument = this.isXML(document); + + features.brokenStarGEBTN + = features.starSelectsClosedQSA + = features.idGetsName + = features.brokenMixedCaseQSA + = features.brokenGEBCN + = features.brokenCheckedQSA + = features.brokenEmptyAttributeQSA + = features.isHTMLDocument + = features.nativeMatchesSelector + = false; + + var starSelectsClosed, starSelectsComments, + brokenSecondClassNameGEBCN, cachedGetElementsByClassName, + brokenFormAttributeGetter; + + var selected, id = 'slick_uniqueid'; + var testNode = document.createElement('div'); + + var testRoot = document.body || document.getElementsByTagName('body')[0] || root; + testRoot.appendChild(testNode); + + // on non-HTML documents innerHTML and getElementsById doesnt work properly + try { + testNode.innerHTML = '<a id="'+id+'"></a>'; + features.isHTMLDocument = !!document.getElementById(id); + } catch(e){}; + + if (features.isHTMLDocument){ + + testNode.style.display = 'none'; + + // IE returns comment nodes for getElementsByTagName('*') for some documents + testNode.appendChild(document.createComment('')); + starSelectsComments = (testNode.getElementsByTagName('*').length > 1); + + // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents + try { + testNode.innerHTML = 'foo</foo>'; + selected = testNode.getElementsByTagName('*'); + starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + features.brokenStarGEBTN = starSelectsComments || starSelectsClosed; + + // IE returns elements with the name instead of just id for getElementsById for some documents + try { + testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>'; + features.idGetsName = document.getElementById(id) === testNode.firstChild; + } catch(e){}; + + if (testNode.getElementsByClassName){ + + // Safari 3.2 getElementsByClassName caches results + try { + testNode.innerHTML = '<a class="f"></a><a class="b"></a>'; + testNode.getElementsByClassName('b').length; + testNode.firstChild.className = 'b'; + cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2); + } catch(e){}; + + // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one + try { + testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>'; + brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); + } catch(e){}; + + features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; + } + + if (testNode.querySelectorAll){ + // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents + try { + testNode.innerHTML = 'foo</foo>'; + selected = testNode.querySelectorAll('*'); + features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode + try { + testNode.innerHTML = '<a class="MiX"></a>'; + features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length; + } catch(e){}; + + // Webkit and Opera dont return selected options on querySelectorAll + try { + testNode.innerHTML = '<select><option selected="selected">a</option></select>'; + features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0); + } catch(e){}; + + // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll + try { + testNode.innerHTML = '<a class=""></a>'; + features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0); + } catch(e){}; + + } + + // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input + try { + testNode.innerHTML = '<form action="s"><input id="action"/></form>'; + brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's'); + } catch(e){}; + + // native matchesSelector function + + features.nativeMatchesSelector = root.matches || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector; + if (features.nativeMatchesSelector) try { + // if matchesSelector trows errors on incorrect sintaxes we can use it + features.nativeMatchesSelector.call(root, ':slick'); + features.nativeMatchesSelector = null; + } catch(e){}; + + } + + try { + root.slick_expando = 1; + delete root.slick_expando; + features.getUID = this.getUIDHTML; + } catch(e) { + features.getUID = this.getUIDXML; + } + + testRoot.removeChild(testNode); + testNode = selected = testRoot = null; + + // getAttribute + + features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){ + var method = this.attributeGetters[name]; + if (method) return method.call(node); + var attributeNode = node.getAttributeNode(name); + return (attributeNode) ? attributeNode.nodeValue : null; + } : function(node, name){ + var method = this.attributeGetters[name]; + return (method) ? method.call(node) : node.getAttribute(name); + }; + + // hasAttribute + + features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) { + return node.hasAttribute(attribute); + } : function(node, attribute) { + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }; + + // contains + // FIXME: Add specs: local.contains should be different for xml and html documents? + var nativeRootContains = root && this.isNativeCode(root.contains), + nativeDocumentContains = document && this.isNativeCode(document.contains); + + features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){ + return context.contains(node); + } : (nativeRootContains && !nativeDocumentContains) ? function(context, node){ + // IE8 does not have .contains on document. + return context === node || ((context === document) ? document.documentElement : context).contains(node); + } : (root && root.compareDocumentPosition) ? function(context, node){ + return context === node || !!(context.compareDocumentPosition(node) & 16); + } : function(context, node){ + if (node) do { + if (node === context) return true; + } while ((node = node.parentNode)); + return false; + }; + + // document order sorting + // credits to Sizzle (http://sizzlejs.com/) + + features.documentSorter = (root.compareDocumentPosition) ? function(a, b){ + if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0; + return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + } : ('sourceIndex' in root) ? function(a, b){ + if (!a.sourceIndex || !b.sourceIndex) return 0; + return a.sourceIndex - b.sourceIndex; + } : (document.createRange) ? function(a, b){ + if (!a.ownerDocument || !b.ownerDocument) return 0; + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + return aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + } : null ; + + root = null; + + for (feature in features){ + this[feature] = features[feature]; + } +}; + +// Main Method + +var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/, + reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/, + qsaFailExpCache = {}; + +local.search = function(context, expression, append, first){ + + var found = this.found = (first) ? null : (append || []); + + if (!context) return found; + else if (context.navigator) context = context.document; // Convert the node from a window to a document + else if (!context.nodeType) return found; + + // setup + + var parsed, i, + uniques = this.uniques = {}, + hasOthers = !!(append && append.length), + contextIsDocument = (context.nodeType == 9); + + if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context); + + // avoid duplicating items already in the append array + if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true; + + // expression checks + + if (typeof expression == 'string'){ // expression is a string + + /*<simple-selectors-override>*/ + var simpleSelector = expression.match(reSimpleSelector); + simpleSelectors: if (simpleSelector) { + + var symbol = simpleSelector[1], + name = simpleSelector[2], + node, nodes; + + if (!symbol){ + + if (name == '*' && this.brokenStarGEBTN) break simpleSelectors; + nodes = context.getElementsByTagName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + } else if (symbol == '#'){ + + if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors; + node = context.getElementById(name); + if (!node) return found; + if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors; + if (first) return node || null; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + + } else if (symbol == '.'){ + + if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors; + if (context.getElementsByClassName && !this.brokenGEBCN){ + nodes = context.getElementsByClassName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } else { + var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)'); + nodes = context.getElementsByTagName('*'); + for (i = 0; node = nodes[i++];){ + className = node.className; + if (!(className && matchClass.test(className))) continue; + if (first) return node; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } + + } + + if (hasOthers) this.sort(found); + return (first) ? null : found; + + } + /*</simple-selectors-override>*/ + + /*<query-selector-override>*/ + querySelector: if (context.querySelectorAll) { + + if (!this.isHTMLDocument + || qsaFailExpCache[expression] + //TODO: only skip when expression is actually mixed case + || this.brokenMixedCaseQSA + || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) + || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) + || (!contextIsDocument //Abort when !contextIsDocument and... + // there are multiple expressions in the selector + // since we currently only fix non-document rooted QSA for single expression selectors + && expression.indexOf(',') > -1 + ) + || Slick.disableQSA + ) break querySelector; + + var _expression = expression, _context = context; + if (!contextIsDocument){ + // non-document rooted QSA + // credits to Andrew Dupont + var currentId = _context.getAttribute('id'), slickid = 'slickid__'; + _context.setAttribute('id', slickid); + _expression = '#' + slickid + ' ' + _expression; + context = _context.parentNode; + } + + try { + if (first) return context.querySelector(_expression) || null; + else nodes = context.querySelectorAll(_expression); + } catch(e) { + qsaFailExpCache[expression] = 1; + break querySelector; + } finally { + if (!contextIsDocument){ + if (currentId) _context.setAttribute('id', currentId); + else _context.removeAttribute('id'); + context = _context; + } + } + + if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){ + if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node); + } else for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + if (hasOthers) this.sort(found); + return found; + + } + /*</query-selector-override>*/ + + parsed = this.Slick.parse(expression); + if (!parsed.length) return found; + } else if (expression == null){ // there is no expression + return found; + } else if (expression.Slick){ // expression is a parsed Slick object + parsed = expression; + } else if (this.contains(context.documentElement || context, expression)){ // expression is a node + (found) ? found.push(expression) : found = expression; + return found; + } else { // other junk + return found; + } + + /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ + + // cache elements for the nth selectors + + this.posNTH = {}; + this.posNTHLast = {}; + this.posNTHType = {}; + this.posNTHTypeLast = {}; + + /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ + + // if append is null and there is only a single selector with one expression use pushArray, else use pushUID + this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID; + + if (found == null) found = []; + + // default engine + + var j, m, n; + var combinator, tag, id, classList, classes, attributes, pseudos; + var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions; + + search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){ + + combinator = 'combinator:' + currentBit.combinator; + if (!this[combinator]) continue search; + + tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase(); + id = currentBit.id; + classList = currentBit.classList; + classes = currentBit.classes; + attributes = currentBit.attributes; + pseudos = currentBit.pseudos; + lastBit = (j === (currentExpression.length - 1)); + + this.bitUniques = {}; + + if (lastBit){ + this.uniques = uniques; + this.found = found; + } else { + this.uniques = {}; + this.found = []; + } + + if (j === 0){ + this[combinator](context, tag, id, classes, attributes, pseudos, classList); + if (first && lastBit && found.length) break search; + } else { + if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){ + this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + if (found.length) break search; + } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + } + + currentItems = this.found; + } + + // should sort if there are nodes in append and if you pass multiple expressions. + if (hasOthers || (parsed.expressions.length > 1)) this.sort(found); + + return (first) ? (found[0] || null) : found; +}; + +// Utils + +local.uidx = 1; +local.uidk = 'slick-uniqueid'; + +local.getUIDXML = function(node){ + var uid = node.getAttribute(this.uidk); + if (!uid){ + uid = this.uidx++; + node.setAttribute(this.uidk, uid); + } + return uid; +}; + +local.getUIDHTML = function(node){ + return node.uniqueNumber || (node.uniqueNumber = this.uidx++); +}; + +// sort based on the setDocument documentSorter method. + +local.sort = function(results){ + if (!this.documentSorter) return results; + results.sort(this.documentSorter); + return results; +}; + +/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ + +local.cacheNTH = {}; + +local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/; + +local.parseNTHArgument = function(argument){ + var parsed = argument.match(this.matchNTH); + if (!parsed) return false; + var special = parsed[2] || false; + var a = parsed[1] || 1; + if (a == '-') a = -1; + var b = +parsed[3] || 0; + parsed = + (special == 'n') ? {a: a, b: b} : + (special == 'odd') ? {a: 2, b: 1} : + (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a}; + + return (this.cacheNTH[argument] = parsed); +}; + +local.createNTHPseudo = function(child, sibling, positions, ofType){ + return function(node, argument){ + var uid = this.getUID(node); + if (!this[positions][uid]){ + var parent = node.parentNode; + if (!parent) return false; + var el = parent[child], count = 1; + if (ofType){ + var nodeName = node.nodeName; + do { + if (el.nodeName != nodeName) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } else { + do { + if (el.nodeType != 1) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } + } + argument = argument || 'n'; + var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument); + if (!parsed) return false; + var a = parsed.a, b = parsed.b, pos = this[positions][uid]; + if (a == 0) return b == pos; + if (a > 0){ + if (pos < b) return false; + } else { + if (b < pos) return false; + } + return ((pos - b) % a) == 0; + }; +}; + +/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ + +local.pushArray = function(node, tag, id, classes, attributes, pseudos){ + if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node); +}; + +local.pushUID = function(node, tag, id, classes, attributes, pseudos){ + var uid = this.getUID(node); + if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){ + this.uniques[uid] = true; + this.found.push(node); + } +}; + +local.matchNode = function(node, selector){ + if (this.isHTMLDocument && this.nativeMatchesSelector){ + try { + return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); + } catch(matchError) {} + } + + var parsed = this.Slick.parse(selector); + if (!parsed) return true; + + // simple (single) selectors + var expressions = parsed.expressions, simpleExpCounter = 0, i; + for (i = 0; (currentExpression = expressions[i]); i++){ + if (currentExpression.length == 1){ + var exp = currentExpression[0]; + if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; + simpleExpCounter++; + } + } + + if (simpleExpCounter == parsed.length) return false; + + var nodes = this.search(this.document, parsed), item; + for (i = 0; item = nodes[i++];){ + if (item === node) return true; + } + return false; +}; + +local.matchPseudo = function(node, name, argument){ + var pseudoName = 'pseudo:' + name; + if (this[pseudoName]) return this[pseudoName](node, argument); + var attribute = this.getAttribute(node, name); + return (argument) ? argument == attribute : !!attribute; +}; + +local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ + if (tag){ + var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase(); + if (tag == '*'){ + if (nodeName < '@') return false; // Fix for comment nodes and closed nodes + } else { + if (nodeName != tag) return false; + } + } + + if (id && node.getAttribute('id') != id) return false; + + var i, part, cls; + if (classes) for (i = classes.length; i--;){ + cls = this.getAttribute(node, 'class'); + if (!(cls && classes[i].regexp.test(cls))) return false; + } + if (attributes) for (i = attributes.length; i--;){ + part = attributes[i]; + if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false; + } + if (pseudos) for (i = pseudos.length; i--;){ + part = pseudos[i]; + if (!this.matchPseudo(node, part.key, part.value)) return false; + } + return true; +}; + +var combinators = { + + ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level + + var i, item, children; + + if (this.isHTMLDocument){ + getById: if (id){ + item = this.document.getElementById(id); + if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){ + // all[id] returns all the elements with that name or id inside node + // if theres just one it will return the element, else it will be a collection + children = node.all[id]; + if (!children) return; + if (!children[0]) children = [children]; + for (i = 0; item = children[i++];){ + var idNode = item.getAttributeNode('id'); + if (idNode && idNode.nodeValue == id){ + this.push(item, tag, null, classes, attributes, pseudos); + break; + } + } + return; + } + if (!item){ + // if the context is in the dom we return, else we will try GEBTN, breaking the getById label + if (this.contains(this.root, node)) return; + else break getById; + } else if (this.document !== node && !this.contains(node, item)) return; + this.push(item, tag, null, classes, attributes, pseudos); + return; + } + getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){ + children = node.getElementsByClassName(classList.join(' ')); + if (!(children && children.length)) break getByClass; + for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos); + return; + } + } + getByTag: { + children = node.getElementsByTagName(tag); + if (!(children && children.length)) break getByTag; + if (!this.brokenStarGEBTN) tag = null; + for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos); + } + }, + + '>': function(node, tag, id, classes, attributes, pseudos){ // direct children + if ((node = node.firstChild)) do { + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + } while ((node = node.nextSibling)); + }, + + '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling + while ((node = node.nextSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '^': function(node, tag, id, classes, attributes, pseudos){ // first child + node = node.firstChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings + while ((node = node.nextSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + }, + + '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling + this['combinator:+'](node, tag, id, classes, attributes, pseudos); + this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + }, + + '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings + this['combinator:~'](node, tag, id, classes, attributes, pseudos); + this['combinator:!~'](node, tag, id, classes, attributes, pseudos); + }, + + '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document + while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level) + node = node.parentNode; + if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling + while ((node = node.previousSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '!^': function(node, tag, id, classes, attributes, pseudos){ // last child + node = node.lastChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings + while ((node = node.previousSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + } + +}; + +for (var c in combinators) local['combinator:' + c] = combinators[c]; + +var pseudos = { + + /*<pseudo-selectors>*/ + + 'empty': function(node){ + var child = node.firstChild; + return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length; + }, + + 'not': function(node, expression){ + return !this.matchNode(node, expression); + }, + + 'contains': function(node, text){ + return (node.innerText || node.textContent || '').indexOf(text) > -1; + }, + + 'first-child': function(node){ + while ((node = node.previousSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'last-child': function(node){ + while ((node = node.nextSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'only-child': function(node){ + var prev = node; + while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeType == 1) return false; + return true; + }, + + /*<nth-pseudo-selectors>*/ + + 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'), + + 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'), + + 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true), + + 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), + + 'index': function(node, index){ + return this['pseudo:nth-child'](node, '' + (index + 1)); + }, + + 'even': function(node){ + return this['pseudo:nth-child'](node, '2n'); + }, + + 'odd': function(node){ + return this['pseudo:nth-child'](node, '2n+1'); + }, + + /*</nth-pseudo-selectors>*/ + + /*<of-type-pseudo-selectors>*/ + + 'first-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'last-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'only-of-type': function(node){ + var prev = node, nodeName = node.nodeName; + while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false; + return true; + }, + + /*</of-type-pseudo-selectors>*/ + + // custom pseudos + + 'enabled': function(node){ + return !node.disabled; + }, + + 'disabled': function(node){ + return node.disabled; + }, + + 'checked': function(node){ + return node.checked || node.selected; + }, + + 'focus': function(node){ + return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex')); + }, + + 'root': function(node){ + return (node === this.root); + }, + + 'selected': function(node){ + return node.selected; + } + + /*</pseudo-selectors>*/ +}; + +for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; + +// attributes methods + +var attributeGetters = local.attributeGetters = { + + 'for': function(){ + return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); + }, + + 'href': function(){ + return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href'); + }, + + 'style': function(){ + return (this.style) ? this.style.cssText : this.getAttribute('style'); + }, + + 'tabindex': function(){ + var attributeNode = this.getAttributeNode('tabindex'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; + }, + + 'type': function(){ + return this.getAttribute('type'); + }, + + 'maxlength': function(){ + var attributeNode = this.getAttributeNode('maxLength'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; + } + +}; + +attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength; + +// Slick + +var Slick = local.Slick = (this.Slick || {}); + +Slick.version = '1.1.7'; + +// Slick finder + +Slick.search = function(context, expression, append){ + return local.search(context, expression, append); +}; + +Slick.find = function(context, expression){ + return local.search(context, expression, null, true); +}; + +// Slick containment checker + +Slick.contains = function(container, node){ + local.setDocument(container); + return local.contains(container, node); +}; + +// Slick attribute getter + +Slick.getAttribute = function(node, name){ + local.setDocument(node); + return local.getAttribute(node, name); +}; + +Slick.hasAttribute = function(node, name){ + local.setDocument(node); + return local.hasAttribute(node, name); +}; + +// Slick matcher + +Slick.match = function(node, selector){ + if (!(node && selector)) return false; + if (!selector || selector === node) return true; + local.setDocument(node); + return local.matchNode(node, selector); +}; + +// Slick attribute accessor + +Slick.defineAttributeGetter = function(name, fn){ + local.attributeGetters[name] = fn; + return this; +}; + +Slick.lookupAttributeGetter = function(name){ + return local.attributeGetters[name]; +}; + +// Slick pseudo accessor + +Slick.definePseudo = function(name, fn){ + local['pseudo:' + name] = function(node, argument){ + return fn.call(node, argument); + }; + return this; +}; + +Slick.lookupPseudo = function(name){ + var pseudo = local['pseudo:' + name]; + if (pseudo) return function(argument){ + return pseudo.call(this, argument); + }; + return null; +}; + +// Slick overrides accessor + +Slick.override = function(regexp, fn){ + local.override(regexp, fn); + return this; +}; + +Slick.isXML = local.isXML; + +Slick.uidOf = function(node){ + return local.getUIDHTML(node); +}; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); + + +/* +--- + +name: Element + +description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. + +license: MIT-style license. + +requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder] + +provides: [Element, Elements, $, $$, IFrame, Selectors] + +... +*/ + +var Element = this.Element = function(tag, props){ + var konstructor = Element.Constructors[tag]; + if (konstructor) return konstructor(props); + if (typeof tag != 'string') return document.id(tag).set(props); + + if (!props) props = {}; + + if (!(/^[\w-]+$/).test(tag)){ + var parsed = Slick.parse(tag).expressions[0][0]; + tag = (parsed.tag == '*') ? 'div' : parsed.tag; + if (parsed.id && props.id == null) props.id = parsed.id; + + var attributes = parsed.attributes; + if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){ + attr = attributes[i]; + if (props[attr.key] != null) continue; + + if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; + else if (!attr.value && !attr.operator) props[attr.key] = true; + } + + if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); + } + + return document.newElement(tag, props); +}; + + +if (Browser.Element){ + Element.prototype = Browser.Element.prototype; + // IE8 and IE9 require the wrapping. + Element.prototype._fireEvent = (function(fireEvent){ + return function(type, event){ + return fireEvent.call(this, type, event); + }; + })(Element.prototype.fireEvent); +} + +new Type('Element', Element).mirror(function(name){ + if (Array.prototype[name]) return; + + var obj = {}; + obj[name] = function(){ + var results = [], args = arguments, elements = true; + for (var i = 0, l = this.length; i < l; i++){ + var element = this[i], result = results[i] = element[name].apply(element, args); + elements = (elements && typeOf(result) == 'element'); + } + return (elements) ? new Elements(results) : results; + }; + + Elements.implement(obj); +}); + +if (!Browser.Element){ + Element.parent = Object; + + Element.Prototype = { + '$constructor': Element, + '$family': Function.from('element').hide() + }; + + Element.mirror(function(name, method){ + Element.Prototype[name] = method; + }); +} + +Element.Constructors = {}; + + + +var IFrame = new Type('IFrame', function(){ + var params = Array.link(arguments, { + properties: Type.isObject, + iframe: function(obj){ + return (obj != null); + } + }); + + var props = params.properties || {}, iframe; + if (params.iframe) iframe = document.id(params.iframe); + var onload = props.onload || function(){}; + delete props.onload; + props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); + iframe = new Element(iframe || 'iframe', props); + + var onLoad = function(){ + onload.call(iframe.contentWindow); + }; + + if (window.frames[props.id]) onLoad(); + else iframe.addListener('load', onLoad); + return iframe; +}); + +var Elements = this.Elements = function(nodes){ + if (nodes && nodes.length){ + var uniques = {}, node; + for (var i = 0; node = nodes[i++];){ + var uid = Slick.uidOf(node); + if (!uniques[uid]){ + uniques[uid] = true; + this.push(node); + } + } + } +}; + +Elements.prototype = {length: 0}; +Elements.parent = Array; + +new Type('Elements', Elements).implement({ + + filter: function(filter, bind){ + if (!filter) return this; + return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ + return item.match(filter); + } : filter, bind)); + }.protect(), + + push: function(){ + var length = this.length; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) this[length++] = item; + } + return (this.length = length); + }.protect(), + + unshift: function(){ + var items = []; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) items.push(item); + } + return Array.prototype.unshift.apply(this, items); + }.protect(), + + concat: function(){ + var newElements = new Elements(this); + for (var i = 0, l = arguments.length; i < l; i++){ + var item = arguments[i]; + if (Type.isEnumerable(item)) newElements.append(item); + else newElements.push(item); + } + return newElements; + }.protect(), + + append: function(collection){ + for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); + return this; + }.protect(), + + empty: function(){ + while (this.length) delete this[--this.length]; + return this; + }.protect() + +}); + + + +(function(){ + +// FF, IE +var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; + +splice.call(object, 1, 1); +if (object[1] == 1) Elements.implement('splice', function(){ + var length = this.length; + var result = splice.apply(this, arguments); + while (length >= this.length) delete this[length--]; + return result; +}.protect()); + +Array.forEachMethod(function(method, name){ + Elements.implement(name, method); +}); + +Array.mirror(Elements); + +/*<ltIE8>*/ +var createElementAcceptsHTML; +try { + createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x'); +} catch (e){} + +var escapeQuotes = function(html){ + return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); +}; +/*</ltIE8>*/ + +Document.implement({ + + newElement: function(tag, props){ + if (props && props.checked != null) props.defaultChecked = props.checked; + /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8 + if (createElementAcceptsHTML && props){ + tag = '<' + tag; + if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; + if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; + tag += '>'; + delete props.name; + delete props.type; + } + /*</ltIE8>*/ + return this.id(this.createElement(tag)).set(props); + } + +}); + +})(); + +(function(){ + +Slick.uidOf(window); +Slick.uidOf(document); + +Document.implement({ + + newTextNode: function(text){ + return this.createTextNode(text); + }, + + getDocument: function(){ + return this; + }, + + getWindow: function(){ + return this.window; + }, + + id: (function(){ + + var types = { + + string: function(id, nocash, doc){ + id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); + return (id) ? types.element(id, nocash) : null; + }, + + element: function(el, nocash){ + Slick.uidOf(el); + if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ + var fireEvent = el.fireEvent; + // wrapping needed in IE7, or else crash + el._fireEvent = function(type, event){ + return fireEvent(type, event); + }; + Object.append(el, Element.Prototype); + } + return el; + }, + + object: function(obj, nocash, doc){ + if (obj.toElement) return types.element(obj.toElement(doc), nocash); + return null; + } + + }; + + types.textnode = types.whitespace = types.window = types.document = function(zero){ + return zero; + }; + + return function(el, nocash, doc){ + if (el && el.$family && el.uniqueNumber) return el; + var type = typeOf(el); + return (types[type]) ? types[type](el, nocash, doc || document) : null; + }; + + })() + +}); + +if (window.$ == null) Window.implement('$', function(el, nc){ + return document.id(el, nc, this.document); +}); + +Window.implement({ + + getDocument: function(){ + return this.document; + }, + + getWindow: function(){ + return this; + } + +}); + +[Document, Element].invoke('implement', { + + getElements: function(expression){ + return Slick.search(this, expression, new Elements); + }, + + getElement: function(expression){ + return document.id(Slick.find(this, expression)); + } + +}); + +var contains = {contains: function(element){ + return Slick.contains(this, element); +}}; + +if (!document.contains) Document.implement(contains); +if (!document.createElement('div').contains) Element.implement(contains); + + + +// tree walking + +var injectCombinator = function(expression, combinator){ + if (!expression) return combinator; + + expression = Object.clone(Slick.parse(expression)); + + var expressions = expression.expressions; + for (var i = expressions.length; i--;) + expressions[i][0].combinator = combinator; + + return expression; +}; + +Object.forEach({ + getNext: '~', + getPrevious: '!~', + getParent: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElement(injectCombinator(expression, combinator)); + }); +}); + +Object.forEach({ + getAllNext: '~', + getAllPrevious: '!~', + getSiblings: '~~', + getChildren: '>', + getParents: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElements(injectCombinator(expression, combinator)); + }); +}); + +Element.implement({ + + getFirst: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); + }, + + getLast: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); + }, + + getWindow: function(){ + return this.ownerDocument.window; + }, + + getDocument: function(){ + return this.ownerDocument; + }, + + getElementById: function(id){ + return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); + }, + + match: function(expression){ + return !expression || Slick.match(this, expression); + } + +}); + + + +if (window.$$ == null) Window.implement('$$', function(selector){ + if (arguments.length == 1){ + if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); + else if (Type.isEnumerable(selector)) return new Elements(selector); + } + return new Elements(arguments); +}); + +// Inserters + +var inserters = { + + before: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element); + }, + + after: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element.nextSibling); + }, + + bottom: function(context, element){ + element.appendChild(context); + }, + + top: function(context, element){ + element.insertBefore(context, element.firstChild); + } + +}; + +inserters.inside = inserters.bottom; + + + +// getProperty / setProperty + +var propertyGetters = {}, propertySetters = {}; + +// properties + +var properties = {}; +Array.forEach([ + 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', + 'frameBorder', 'rowSpan', 'tabIndex', 'useMap' +], function(property){ + properties[property.toLowerCase()] = property; +}); + +properties.html = 'innerHTML'; +properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent'; + +Object.forEach(properties, function(real, key){ + propertySetters[key] = function(node, value){ + node[real] = value; + }; + propertyGetters[key] = function(node){ + return node[real]; + }; +}); + +// Booleans + +var bools = [ + 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', + 'disabled', 'readOnly', 'multiple', 'selected', 'noresize', + 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay', + 'loop' +]; + +var booleans = {}; +Array.forEach(bools, function(bool){ + var lower = bool.toLowerCase(); + booleans[lower] = bool; + propertySetters[lower] = function(node, value){ + node[bool] = !!value; + }; + propertyGetters[lower] = function(node){ + return !!node[bool]; + }; +}); + +// Special cases + +Object.append(propertySetters, { + + 'class': function(node, value){ + ('className' in node) ? node.className = (value || '') : node.setAttribute('class', value); + }, + + 'for': function(node, value){ + ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value); + }, + + 'style': function(node, value){ + (node.style) ? node.style.cssText = value : node.setAttribute('style', value); + }, + + 'value': function(node, value){ + node.value = (value != null) ? value : ''; + } + +}); + +propertyGetters['class'] = function(node){ + return ('className' in node) ? node.className || null : node.getAttribute('class'); +}; + +/* <webkit> */ +var el = document.createElement('button'); +// IE sets type as readonly and throws +try { el.type = 'button'; } catch(e){} +if (el.type != 'button') propertySetters.type = function(node, value){ + node.setAttribute('type', value); +}; +el = null; +/* </webkit> */ + +/*<IE>*/ +var input = document.createElement('input'); +input.value = 't'; +input.type = 'submit'; +if (input.value != 't') propertySetters.type = function(node, type){ + var value = node.value; + node.type = type; + node.value = value; +}; +input = null; +/*</IE>*/ + +/* getProperty, setProperty */ + +/* <ltIE9> */ +var pollutesGetAttribute = (function(div){ + div.random = 'attribute'; + return (div.getAttribute('random') == 'attribute'); +})(document.createElement('div')); + +var hasCloneBug = (function(test){ + test.innerHTML = '<object><param name="should_fix" value="the unknown"></object>'; + return test.cloneNode(true).firstChild.childNodes.length != 1; +})(document.createElement('div')); +/* </ltIE9> */ + +var hasClassList = !!document.createElement('div').classList; + +var classes = function(className){ + var classNames = (className || '').clean().split(" "), uniques = {}; + return classNames.filter(function(className){ + if (className !== "" && !uniques[className]) return uniques[className] = className; + }); +}; + +var addToClassList = function(name){ + this.classList.add(name); +}; + +var removeFromClassList = function(name){ + this.classList.remove(name); +}; + +Element.implement({ + + setProperty: function(name, value){ + var setter = propertySetters[name.toLowerCase()]; + if (setter){ + setter(this, value); + } else { + /* <ltIE9> */ + var attributeWhiteList; + if (pollutesGetAttribute) attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + /* </ltIE9> */ + + if (value == null){ + this.removeAttribute(name); + /* <ltIE9> */ + if (pollutesGetAttribute) delete attributeWhiteList[name]; + /* </ltIE9> */ + } else { + this.setAttribute(name, '' + value); + /* <ltIE9> */ + if (pollutesGetAttribute) attributeWhiteList[name] = true; + /* </ltIE9> */ + } + } + return this; + }, + + setProperties: function(attributes){ + for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); + return this; + }, + + getProperty: function(name){ + var getter = propertyGetters[name.toLowerCase()]; + if (getter) return getter(this); + /* <ltIE9> */ + if (pollutesGetAttribute){ + var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + if (!attr) return null; + if (attr.expando && !attributeWhiteList[name]){ + var outer = this.outerHTML; + // segment by the opening tag and find mention of attribute name + if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null; + attributeWhiteList[name] = true; + } + } + /* </ltIE9> */ + var result = Slick.getAttribute(this, name); + return (!result && !Slick.hasAttribute(this, name)) ? null : result; + }, + + getProperties: function(){ + var args = Array.from(arguments); + return args.map(this.getProperty, this).associate(args); + }, + + removeProperty: function(name){ + return this.setProperty(name, null); + }, + + removeProperties: function(){ + Array.each(arguments, this.removeProperty, this); + return this; + }, + + set: function(prop, value){ + var property = Element.Properties[prop]; + (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); + }.overloadSetter(), + + get: function(prop){ + var property = Element.Properties[prop]; + return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); + }.overloadGetter(), + + erase: function(prop){ + var property = Element.Properties[prop]; + (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); + return this; + }, + + hasClass: hasClassList ? function(className){ + return this.classList.contains(className); + } : function(className){ + return this.className.clean().contains(className, ' '); + }, + + addClass: hasClassList ? function(className){ + classes(className).forEach(addToClassList, this); + return this; + } : function(className){ + this.className = classes(className + ' ' + this.className).join(' '); + return this; + }, + + removeClass: hasClassList ? function(className){ + classes(className).forEach(removeFromClassList, this); + return this; + } : function(className){ + var classNames = classes(this.className); + classes(className).forEach(classNames.erase, classNames); + this.className = classNames.join(' '); + return this; + }, + + toggleClass: function(className, force){ + if (force == null) force = !this.hasClass(className); + return (force) ? this.addClass(className) : this.removeClass(className); + }, + + adopt: function(){ + var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; + if (length > 1) parent = fragment = document.createDocumentFragment(); + + for (var i = 0; i < length; i++){ + var element = document.id(elements[i], true); + if (element) parent.appendChild(element); + } + + if (fragment) this.appendChild(fragment); + + return this; + }, + + appendText: function(text, where){ + return this.grab(this.getDocument().newTextNode(text), where); + }, + + grab: function(el, where){ + inserters[where || 'bottom'](document.id(el, true), this); + return this; + }, + + inject: function(el, where){ + inserters[where || 'bottom'](this, document.id(el, true)); + return this; + }, + + replaces: function(el){ + el = document.id(el, true); + el.parentNode.replaceChild(this, el); + return this; + }, + + wraps: function(el, where){ + el = document.id(el, true); + return this.replaces(el).grab(el, where); + }, + + getSelected: function(){ + this.selectedIndex; // Safari 3.2.1 + return new Elements(Array.from(this.options).filter(function(option){ + return option.selected; + })); + }, + + toQueryString: function(){ + var queryString = []; + this.getElements('input, select, textarea').each(function(el){ + var type = el.type; + if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; + + var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ + // IE + return document.id(opt).get('value'); + }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); + + Array.from(value).each(function(val){ + if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); + }); + }); + return queryString.join('&'); + } + +}); + + +// appendHTML + +var appendInserters = { + before: 'beforeBegin', + after: 'afterEnd', + bottom: 'beforeEnd', + top: 'afterBegin', + inside: 'beforeEnd' +}; + +Element.implement('appendHTML', ('insertAdjacentHTML' in document.createElement('div')) ? function(html, where){ + this.insertAdjacentHTML(appendInserters[where || 'bottom'], html); + return this; +} : function(html, where){ + var temp = new Element('div', {html: html}), + children = temp.childNodes, + fragment = temp.firstChild; + + if (!fragment) return this; + if (children.length > 1){ + fragment = document.createDocumentFragment(); + for (var i = 0, l = children.length; i < l; i++){ + fragment.appendChild(children[i]); + } + } + + inserters[where || 'bottom'](fragment, this); + return this; +}); + +var collected = {}, storage = {}; + +var get = function(uid){ + return (storage[uid] || (storage[uid] = {})); +}; + +var clean = function(item){ + var uid = item.uniqueNumber; + if (item.removeEvents) item.removeEvents(); + if (item.clearAttributes) item.clearAttributes(); + if (uid != null){ + delete collected[uid]; + delete storage[uid]; + } + return item; +}; + +var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; + +Element.implement({ + + destroy: function(){ + var children = clean(this).getElementsByTagName('*'); + Array.each(children, clean); + Element.dispose(this); + return null; + }, + + empty: function(){ + Array.from(this.childNodes).each(Element.dispose); + return this; + }, + + dispose: function(){ + return (this.parentNode) ? this.parentNode.removeChild(this) : this; + }, + + clone: function(contents, keepid){ + contents = contents !== false; + var clone = this.cloneNode(contents), ce = [clone], te = [this], i; + + if (contents){ + ce.append(Array.from(clone.getElementsByTagName('*'))); + te.append(Array.from(this.getElementsByTagName('*'))); + } + + for (i = ce.length; i--;){ + var node = ce[i], element = te[i]; + if (!keepid) node.removeAttribute('id'); + /*<ltIE9>*/ + if (node.clearAttributes){ + node.clearAttributes(); + node.mergeAttributes(element); + node.removeAttribute('uniqueNumber'); + if (node.options){ + var no = node.options, eo = element.options; + for (var j = no.length; j--;) no[j].selected = eo[j].selected; + } + } + /*</ltIE9>*/ + var prop = formProps[element.tagName.toLowerCase()]; + if (prop && element[prop]) node[prop] = element[prop]; + } + + /*<ltIE9>*/ + if (hasCloneBug){ + var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); + for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; + } + /*</ltIE9>*/ + return document.id(clone); + } + +}); + +[Element, Window, Document].invoke('implement', { + + addListener: function(type, fn){ + if (window.attachEvent && !window.addEventListener){ + collected[Slick.uidOf(this)] = this; + } + if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); + else this.attachEvent('on' + type, fn); + return this; + }, + + removeListener: function(type, fn){ + if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); + else this.detachEvent('on' + type, fn); + return this; + }, + + retrieve: function(property, dflt){ + var storage = get(Slick.uidOf(this)), prop = storage[property]; + if (dflt != null && prop == null) prop = storage[property] = dflt; + return prop != null ? prop : null; + }, + + store: function(property, value){ + var storage = get(Slick.uidOf(this)); + storage[property] = value; + return this; + }, + + eliminate: function(property){ + var storage = get(Slick.uidOf(this)); + delete storage[property]; + return this; + } + +}); + +/*<ltIE9>*/ +if (window.attachEvent && !window.addEventListener){ + var gc = function(){ + Object.each(collected, clean); + if (window.CollectGarbage) CollectGarbage(); + window.removeListener('unload', gc); + } + window.addListener('unload', gc); +} +/*</ltIE9>*/ + +Element.Properties = {}; + + + +Element.Properties.style = { + + set: function(style){ + this.style.cssText = style; + }, + + get: function(){ + return this.style.cssText; + }, + + erase: function(){ + this.style.cssText = ''; + } + +}; + +Element.Properties.tag = { + + get: function(){ + return this.tagName.toLowerCase(); + } + +}; + +Element.Properties.html = { + + set: function(html){ + if (html == null) html = ''; + else if (typeOf(html) == 'array') html = html.join(''); + this.innerHTML = html; + }, + + erase: function(){ + this.innerHTML = ''; + } + +}; + +var supportsHTML5Elements = true, supportsTableInnerHTML = true, supportsTRInnerHTML = true; + +/*<ltIE9>*/ +// technique by jdbarlett - http://jdbartlett.com/innershiv/ +var div = document.createElement('div'); +div.innerHTML = '<nav></nav>'; +supportsHTML5Elements = (div.childNodes.length == 1); +if (!supportsHTML5Elements){ + var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), + fragment = document.createDocumentFragment(), l = tags.length; + while (l--) fragment.createElement(tags[l]); +} +div = null; +/*</ltIE9>*/ + +/*<IE>*/ +supportsTableInnerHTML = Function.attempt(function(){ + var table = document.createElement('table'); + table.innerHTML = '<tr><td></td></tr>'; + return true; +}); + +/*<ltFF4>*/ +var tr = document.createElement('tr'), html = '<td></td>'; +tr.innerHTML = html; +supportsTRInnerHTML = (tr.innerHTML == html); +tr = null; +/*</ltFF4>*/ + +if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){ + + Element.Properties.html.set = (function(set){ + + var translations = { + table: [1, '<table>', '</table>'], + select: [1, '<select>', '</select>'], + tbody: [2, '<table><tbody>', '</tbody></table>'], + tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] + }; + + translations.thead = translations.tfoot = translations.tbody; + + return function(html){ + var wrap = translations[this.get('tag')]; + if (!wrap && !supportsHTML5Elements) wrap = [0, '', '']; + if (!wrap) return set.call(this, html); + + var level = wrap[0], wrapper = document.createElement('div'), target = wrapper; + if (!supportsHTML5Elements) fragment.appendChild(wrapper); + wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join(''); + while (level--) target = target.firstChild; + this.empty().adopt(target.childNodes); + if (!supportsHTML5Elements) fragment.removeChild(wrapper); + wrapper = null; + }; + + })(Element.Properties.html.set); +} +/*</IE>*/ + +/*<ltIE9>*/ +var testForm = document.createElement('form'); +testForm.innerHTML = '<select><option>s</option></select>'; + +if (testForm.firstChild.value != 's') Element.Properties.value = { + + set: function(value){ + var tag = this.get('tag'); + if (tag != 'select') return this.setProperty('value', value); + var options = this.getElements('option'); + value = String(value); + for (var i = 0; i < options.length; i++){ + var option = options[i], + attr = option.getAttributeNode('value'), + optionValue = (attr && attr.specified) ? option.value : option.get('text'); + if (optionValue === value) return option.selected = true; + } + }, + + get: function(){ + var option = this, tag = option.get('tag'); + + if (tag != 'select' && tag != 'option') return this.getProperty('value'); + + if (tag == 'select' && !(option = option.getSelected()[0])) return ''; + + var attr = option.getAttributeNode('value'); + return (attr && attr.specified) ? option.value : option.get('text'); + } + +}; +testForm = null; +/*</ltIE9>*/ + +/*<IE>*/ +if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = { + set: function(id){ + this.id = this.getAttributeNode('id').value = id; + }, + get: function(){ + return this.id || null; + }, + erase: function(){ + this.id = this.getAttributeNode('id').value = ''; + } +}; +/*</IE>*/ + +})(); + + +/* +--- + +name: Element.Style + +description: Contains methods for interacting with the styles of Elements in a fashionable way. + +license: MIT-style license. + +requires: Element + +provides: Element.Style + +... +*/ + +(function(){ + +var html = document.html, el; + +//<ltIE9> +// Check for oldIE, which does not remove styles when they're set to null +el = document.createElement('div'); +el.style.color = 'red'; +el.style.color = null; +var doesNotRemoveStyles = el.style.color == 'red'; + +// check for oldIE, which returns border* shorthand styles in the wrong order (color-width-style instead of width-style-color) +var border = '1px solid #123abc'; +el.style.border = border; +var returnsBordersInWrongOrder = el.style.border != border; +el = null; +//</ltIE9> + +var hasGetComputedStyle = !!window.getComputedStyle; + +Element.Properties.styles = {set: function(styles){ + this.setStyles(styles); +}}; + +var hasOpacity = (html.style.opacity != null), + hasFilter = (html.style.filter != null), + reAlpha = /alpha\(opacity=([\d.]+)\)/i; + +var setVisibility = function(element, opacity){ + element.store('$opacity', opacity); + element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden'; +}; + +//<ltIE9> +var setFilter = function(element, regexp, value){ + var style = element.style, + filter = style.filter || element.getComputedStyle('filter') || ''; + style.filter = (regexp.test(filter) ? filter.replace(regexp, value) : filter + ' ' + value).trim(); + if (!style.filter) style.removeAttribute('filter'); +}; +//</ltIE9> + +var setOpacity = (hasOpacity ? function(element, opacity){ + element.style.opacity = opacity; +} : (hasFilter ? function(element, opacity){ + if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; + if (opacity == null || opacity == 1){ + setFilter(element, reAlpha, ''); + if (opacity == 1 && getOpacity(element) != 1) setFilter(element, reAlpha, 'alpha(opacity=100)'); + } else { + setFilter(element, reAlpha, 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')'); + } +} : setVisibility)); + +var getOpacity = (hasOpacity ? function(element){ + var opacity = element.style.opacity || element.getComputedStyle('opacity'); + return (opacity == '') ? 1 : opacity.toFloat(); +} : (hasFilter ? function(element){ + var filter = (element.style.filter || element.getComputedStyle('filter')), + opacity; + if (filter) opacity = filter.match(reAlpha); + return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); +} : function(element){ + var opacity = element.retrieve('$opacity'); + if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1); + return opacity; +})); + +var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat', + namedPositions = {left: '0%', top: '0%', center: '50%', right: '100%', bottom: '100%'}, + hasBackgroundPositionXY = (html.style.backgroundPositionX != null); + +//<ltIE9> +var removeStyle = function(style, property){ + if (property == 'backgroundPosition'){ + style.removeAttribute(property + 'X'); + property += 'Y'; + } + style.removeAttribute(property); +}; +//</ltIE9> + +Element.implement({ + + getComputedStyle: function(property){ + if (!hasGetComputedStyle && this.currentStyle) return this.currentStyle[property.camelCase()]; + var defaultView = Element.getDocument(this).defaultView, + computed = defaultView ? defaultView.getComputedStyle(this, null) : null; + return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : ''; + }, + + setStyle: function(property, value){ + if (property == 'opacity'){ + if (value != null) value = parseFloat(value); + setOpacity(this, value); + return this; + } + property = (property == 'float' ? floatName : property).camelCase(); + if (typeOf(value) != 'string'){ + var map = (Element.Styles[property] || '@').split(' '); + value = Array.from(value).map(function(val, i){ + if (!map[i]) return ''; + return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; + }).join(' '); + } else if (value == String(Number(value))){ + value = Math.round(value); + } + this.style[property] = value; + //<ltIE9> + if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){ + removeStyle(this.style, property); + } + //</ltIE9> + return this; + }, + + getStyle: function(property){ + if (property == 'opacity') return getOpacity(this); + property = (property == 'float' ? floatName : property).camelCase(); + var result = this.style[property]; + if (!result || property == 'zIndex'){ + if (Element.ShortStyles.hasOwnProperty(property)){ + result = []; + for (var s in Element.ShortStyles[property]) result.push(this.getStyle(s)); + return result.join(' '); + } + result = this.getComputedStyle(property); + } + if (hasBackgroundPositionXY && /^backgroundPosition[XY]?$/.test(property)){ + return result.replace(/(top|right|bottom|left)/g, function(position){ + return namedPositions[position]; + }) || '0px'; + } + if (!result && property == 'backgroundPosition') return '0px 0px'; + if (result){ + result = String(result); + var color = result.match(/rgba?\([\d\s,]+\)/); + if (color) result = result.replace(color[0], color[0].rgbToHex()); + } + if (!hasGetComputedStyle && !this.style[property]){ + if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){ + var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; + values.each(function(value){ + size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); + }, this); + return this['offset' + property.capitalize()] - size + 'px'; + } + if ((/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){ + return '0px'; + } + } + //<ltIE9> + if (returnsBordersInWrongOrder && /^border(Top|Right|Bottom|Left)?$/.test(property) && /^#/.test(result)){ + return result.replace(/^(.+)\s(.+)\s(.+)$/, '$2 $3 $1'); + } + //</ltIE9> + return result; + }, + + setStyles: function(styles){ + for (var style in styles) this.setStyle(style, styles[style]); + return this; + }, + + getStyles: function(){ + var result = {}; + Array.flatten(arguments).each(function(key){ + result[key] = this.getStyle(key); + }, this); + return result; + } + +}); + +Element.Styles = { + left: '@px', top: '@px', bottom: '@px', right: '@px', + width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', + backgroundColor: 'rgb(@, @, @)', backgroundSize: '@px', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', + fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', + margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', + borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', + zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' +}; + + + + + +Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; + +['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ + var Short = Element.ShortStyles; + var All = Element.Styles; + ['margin', 'padding'].each(function(style){ + var sd = style + direction; + Short[style][sd] = All[sd] = '@px'; + }); + var bd = 'border' + direction; + Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; + var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; + Short[bd] = {}; + Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; + Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; + Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; +}); + +if (hasBackgroundPositionXY) Element.ShortStyles.backgroundPosition = {backgroundPositionX: '@', backgroundPositionY: '@'}; +})(); + + +/* +--- + +name: Element.Event + +description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary. + +license: MIT-style license. + +requires: [Element, Event] + +provides: Element.Event + +... +*/ + +(function(){ + +Element.Properties.events = {set: function(events){ + this.addEvents(events); +}}; + +[Element, Window, Document].invoke('implement', { + + addEvent: function(type, fn){ + var events = this.retrieve('events', {}); + if (!events[type]) events[type] = {keys: [], values: []}; + if (events[type].keys.contains(fn)) return this; + events[type].keys.push(fn); + var realType = type, + custom = Element.Events[type], + condition = fn, + self = this; + if (custom){ + if (custom.onAdd) custom.onAdd.call(this, fn, type); + if (custom.condition){ + condition = function(event){ + if (custom.condition.call(this, event, type)) return fn.call(this, event); + return true; + }; + } + if (custom.base) realType = Function.from(custom.base).call(this, type); + } + var defn = function(){ + return fn.call(self); + }; + var nativeEvent = Element.NativeEvents[realType]; + if (nativeEvent){ + if (nativeEvent == 2){ + defn = function(event){ + event = new DOMEvent(event, self.getWindow()); + if (condition.call(self, event) === false) event.stop(); + }; + } + this.addListener(realType, defn, arguments[2]); + } + events[type].values.push(defn); + return this; + }, + + removeEvent: function(type, fn){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + var list = events[type]; + var index = list.keys.indexOf(fn); + if (index == -1) return this; + var value = list.values[index]; + delete list.keys[index]; + delete list.values[index]; + var custom = Element.Events[type]; + if (custom){ + if (custom.onRemove) custom.onRemove.call(this, fn, type); + if (custom.base) type = Function.from(custom.base).call(this, type); + } + return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; + }, + + addEvents: function(events){ + for (var event in events) this.addEvent(event, events[event]); + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + var attached = this.retrieve('events'); + if (!attached) return this; + if (!events){ + for (type in attached) this.removeEvents(type); + this.eliminate('events'); + } else if (attached[events]){ + attached[events].keys.each(function(fn){ + this.removeEvent(events, fn); + }, this); + delete attached[events]; + } + return this; + }, + + fireEvent: function(type, args, delay){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + args = Array.from(args); + + events[type].keys.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + cloneEvents: function(from, type){ + from = document.id(from); + var events = from.retrieve('events'); + if (!events) return this; + if (!type){ + for (var eventType in events) this.cloneEvents(from, eventType); + } else if (events[type]){ + events[type].keys.each(function(fn){ + this.addEvent(type, fn); + }, this); + } + return this; + } + +}); + +Element.NativeEvents = { + click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons + mousewheel: 2, DOMMouseScroll: 2, //mouse wheel + mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement + keydown: 2, keypress: 2, keyup: 2, //keyboard + orientationchange: 2, // mobile + touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch + gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture + focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements + load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window + hashchange: 1, popstate: 2, // history + error: 1, abort: 1, scroll: 1 //misc +}; + +Element.Events = { + mousewheel: { + base: 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll' + } +}; + +var check = function(event){ + var related = event.relatedTarget; + if (related == null) return true; + if (!related) return false; + return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related)); +}; + +if ('onmouseenter' in document.documentElement){ + Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2; + Element.MouseenterCheck = check; +} else { + Element.Events.mouseenter = { + base: 'mouseover', + condition: check + }; + + Element.Events.mouseleave = { + base: 'mouseout', + condition: check + }; +} + +/*<ltIE9>*/ +if (!window.addEventListener){ + Element.NativeEvents.propertychange = 2; + Element.Events.change = { + base: function(){ + var type = this.type; + return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change'; + }, + condition: function(event){ + return event.type != 'propertychange' || event.event.propertyName == 'checked'; + } + }; +} +/*</ltIE9>*/ + + + +})(); + + +/* +--- + +name: Element.Delegation + +description: Extends the Element native object to include the delegate method for more efficient event management. + +license: MIT-style license. + +requires: [Element.Event] + +provides: [Element.Delegation] + +... +*/ + +(function(){ + +var eventListenerSupport = !!window.addEventListener; + +Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2; + +var bubbleUp = function(self, match, fn, event, target){ + while (target && target != self){ + if (match(target, event)) return fn.call(target, event, target); + target = document.id(target.parentNode); + } +}; + +var map = { + mouseenter: { + base: 'mouseover', + condition: Element.MouseenterCheck + }, + mouseleave: { + base: 'mouseout', + condition: Element.MouseenterCheck + }, + focus: { + base: 'focus' + (eventListenerSupport ? '' : 'in'), + capture: true + }, + blur: { + base: eventListenerSupport ? 'blur' : 'focusout', + capture: true + } +}; + +/*<ltIE9>*/ +var _key = '$delegation:'; +var formObserver = function(type){ + + return { + + base: 'focusin', + + remove: function(self, uid){ + var list = self.retrieve(_key + type + 'listeners', {})[uid]; + if (list && list.forms) for (var i = list.forms.length; i--;){ + list.forms[i].removeEvent(type, list.fns[i]); + } + }, + + listen: function(self, match, fn, event, target, uid){ + var form = (target.get('tag') == 'form') ? target : event.target.getParent('form'); + if (!form) return; + + var listeners = self.retrieve(_key + type + 'listeners', {}), + listener = listeners[uid] || {forms: [], fns: []}, + forms = listener.forms, fns = listener.fns; + + if (forms.indexOf(form) != -1) return; + forms.push(form); + + var _fn = function(event){ + bubbleUp(self, match, fn, event, target); + }; + form.addEvent(type, _fn); + fns.push(_fn); + + listeners[uid] = listener; + self.store(_key + type + 'listeners', listeners); + } + }; +}; + +var inputObserver = function(type){ + return { + base: 'focusin', + listen: function(self, match, fn, event, target){ + var events = {blur: function(){ + this.removeEvents(events); + }}; + events[type] = function(event){ + bubbleUp(self, match, fn, event, target); + }; + event.target.addEvents(events); + } + }; +}; + +if (!eventListenerSupport) Object.append(map, { + submit: formObserver('submit'), + reset: formObserver('reset'), + change: inputObserver('change'), + select: inputObserver('select') +}); +/*</ltIE9>*/ + +var proto = Element.prototype, + addEvent = proto.addEvent, + removeEvent = proto.removeEvent; + +var relay = function(old, method){ + return function(type, fn, useCapture){ + if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture); + var parsed = Slick.parse(type).expressions[0][0]; + if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture); + var newType = parsed.tag; + parsed.pseudos.slice(1).each(function(pseudo){ + newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : ''); + }); + old.call(this, type, fn); + return method.call(this, newType, parsed.pseudos[0].value, fn); + }; +}; + +var delegation = { + + addEvent: function(type, match, fn){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (stored) for (var _uid in stored){ + if (stored[_uid].fn == fn && stored[_uid].match == match) return this; + } + + var _type = type, _match = match, _fn = fn, _map = map[type] || {}; + type = _map.base || _type; + + match = function(target){ + return Slick.match(target, _match); + }; + + var elementEvent = Element.Events[_type]; + if (_map.condition || elementEvent && elementEvent.condition){ + var __match = match, condition = _map.condition || elementEvent.condition; + match = function(target, event){ + return __match(target, event) && condition.call(target, event, type); + }; + } + + var self = this, uid = String.uniqueID(); + var delegator = _map.listen ? function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) _map.listen(self, match, fn, event, target, uid); + } : function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) bubbleUp(self, match, fn, event, target); + }; + + if (!stored) stored = {}; + stored[uid] = { + match: _match, + fn: _fn, + delegator: delegator + }; + storage[_type] = stored; + return addEvent.call(this, type, delegator, _map.capture); + }, + + removeEvent: function(type, match, fn, _uid){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (!stored) return this; + + if (_uid){ + var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {}; + type = _map.base || _type; + if (_map.remove) _map.remove(this, _uid); + delete stored[_uid]; + storage[_type] = stored; + return removeEvent.call(this, type, delegator, _map.capture); + } + + var __uid, s; + if (fn) for (__uid in stored){ + s = stored[__uid]; + if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid); + } else for (__uid in stored){ + s = stored[__uid]; + if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid); + } + return this; + } + +}; + +[Element, Window, Document].invoke('implement', { + addEvent: relay(addEvent, delegation.addEvent), + removeEvent: relay(removeEvent, delegation.removeEvent) +}); + +})(); + + +/* +--- + +name: Element.Dimensions + +description: Contains methods to work with size, scroll, or positioning of Elements and the window object. + +license: MIT-style license. + +credits: + - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). + - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). + +requires: [Element, Element.Style] + +provides: [Element.Dimensions] + +... +*/ + +(function(){ + +var element = document.createElement('div'), + child = document.createElement('div'); +element.style.height = '0'; +element.appendChild(child); +var brokenOffsetParent = (child.offsetParent === element); +element = child = null; + +var isOffset = function(el){ + return styleString(el, 'position') != 'static' || isBody(el); +}; + +var isOffsetStatic = function(el){ + return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName); +}; + +Element.implement({ + + scrollTo: function(x, y){ + if (isBody(this)){ + this.getWindow().scrollTo(x, y); + } else { + this.scrollLeft = x; + this.scrollTop = y; + } + return this; + }, + + getSize: function(){ + if (isBody(this)) return this.getWindow().getSize(); + return {x: this.offsetWidth, y: this.offsetHeight}; + }, + + getScrollSize: function(){ + if (isBody(this)) return this.getWindow().getScrollSize(); + return {x: this.scrollWidth, y: this.scrollHeight}; + }, + + getScroll: function(){ + if (isBody(this)) return this.getWindow().getScroll(); + return {x: this.scrollLeft, y: this.scrollTop}; + }, + + getScrolls: function(){ + var element = this.parentNode, position = {x: 0, y: 0}; + while (element && !isBody(element)){ + position.x += element.scrollLeft; + position.y += element.scrollTop; + element = element.parentNode; + } + return position; + }, + + getOffsetParent: brokenOffsetParent ? function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset; + while ((element = element.parentNode)){ + if (isOffsetCheck(element)) return element; + } + return null; + } : function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + try { + return element.offsetParent; + } catch(e) {} + return null; + }, + + getOffsets: function(){ + var hasGetBoundingClientRect = this.getBoundingClientRect; + + if (hasGetBoundingClientRect){ + var bound = this.getBoundingClientRect(), + html = document.id(this.getDocument().documentElement), + htmlScroll = html.getScroll(), + elemScrolls = this.getScrolls(), + isFixed = (styleString(this, 'position') == 'fixed'); + + return { + x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, + y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop + }; + } + + var element = this, position = {x: 0, y: 0}; + if (isBody(this)) return position; + + while (element && !isBody(element)){ + position.x += element.offsetLeft; + position.y += element.offsetTop; + + element = element.offsetParent; + } + + return position; + }, + + getPosition: function(relative){ + var offset = this.getOffsets(), + scroll = this.getScrolls(); + var position = { + x: offset.x - scroll.x, + y: offset.y - scroll.y + }; + + if (relative && (relative = document.id(relative))){ + var relativePosition = relative.getPosition(); + return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; + } + return position; + }, + + getCoordinates: function(element){ + if (isBody(this)) return this.getWindow().getCoordinates(); + var position = this.getPosition(element), + size = this.getSize(); + var obj = { + left: position.x, + top: position.y, + width: size.x, + height: size.y + }; + obj.right = obj.left + obj.width; + obj.bottom = obj.top + obj.height; + return obj; + }, + + computePosition: function(obj){ + return { + left: obj.x - styleNumber(this, 'margin-left'), + top: obj.y - styleNumber(this, 'margin-top') + }; + }, + + setPosition: function(obj){ + return this.setStyles(this.computePosition(obj)); + } + +}); + + +[Document, Window].invoke('implement', { + + getSize: function(){ + var doc = getCompatElement(this); + return {x: doc.clientWidth, y: doc.clientHeight}; + }, + + getScroll: function(){ + var win = this.getWindow(), doc = getCompatElement(this); + return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; + }, + + getScrollSize: function(){ + var doc = getCompatElement(this), + min = this.getSize(), + body = this.getDocument().body; + + return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)}; + }, + + getPosition: function(){ + return {x: 0, y: 0}; + }, + + getCoordinates: function(){ + var size = this.getSize(); + return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; + } + +}); + +// private methods + +var styleString = Element.getComputedStyle; + +function styleNumber(element, style){ + return styleString(element, style).toInt() || 0; +} + +function borderBox(element){ + return styleString(element, '-moz-box-sizing') == 'border-box'; +} + +function topBorder(element){ + return styleNumber(element, 'border-top-width'); +} + +function leftBorder(element){ + return styleNumber(element, 'border-left-width'); +} + +function isBody(element){ + return (/^(?:body|html)$/i).test(element.tagName); +} + +function getCompatElement(element){ + var doc = element.getDocument(); + return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; +} + +})(); + +//aliases +Element.alias({position: 'setPosition'}); //compatability + +[Window, Document, Element].invoke('implement', { + + getHeight: function(){ + return this.getSize().y; + }, + + getWidth: function(){ + return this.getSize().x; + }, + + getScrollTop: function(){ + return this.getScroll().y; + }, + + getScrollLeft: function(){ + return this.getScroll().x; + }, + + getScrollHeight: function(){ + return this.getScrollSize().y; + }, + + getScrollWidth: function(){ + return this.getScrollSize().x; + }, + + getTop: function(){ + return this.getPosition().y; + }, + + getLeft: function(){ + return this.getPosition().x; + } + +}); + + +/* +--- + +name: Fx + +description: Contains the basic animation logic to be extended by all other Fx Classes. + +license: MIT-style license. + +requires: [Chain, Events, Options] + +provides: Fx + +... +*/ + +(function(){ + +var Fx = this.Fx = new Class({ + + Implements: [Chain, Events, Options], + + options: { + /* + onStart: nil, + onCancel: nil, + onComplete: nil, + */ + fps: 60, + unit: false, + duration: 500, + frames: null, + frameSkip: true, + link: 'ignore' + }, + + initialize: function(options){ + this.subject = this.subject || this; + this.setOptions(options); + }, + + getTransition: function(){ + return function(p){ + return -(Math.cos(Math.PI * p) - 1) / 2; + }; + }, + + step: function(now){ + if (this.options.frameSkip){ + var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval; + this.time = now; + this.frame += frames; + } else { + this.frame++; + } + + if (this.frame < this.frames){ + var delta = this.transition(this.frame / this.frames); + this.set(this.compute(this.from, this.to, delta)); + } else { + this.frame = this.frames; + this.set(this.compute(this.from, this.to, 1)); + this.stop(); + } + }, + + set: function(now){ + return now; + }, + + compute: function(from, to, delta){ + return Fx.compute(from, to, delta); + }, + + check: function(){ + if (!this.isRunning()) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + start: function(from, to){ + if (!this.check(from, to)) return this; + this.from = from; + this.to = to; + this.frame = (this.options.frameSkip) ? 0 : -1; + this.time = null; + this.transition = this.getTransition(); + var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration; + this.duration = Fx.Durations[duration] || duration.toInt(); + this.frameInterval = 1000 / fps; + this.frames = frames || Math.round(this.duration / this.frameInterval); + this.fireEvent('start', this.subject); + pushInstance.call(this, fps); + return this; + }, + + stop: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + if (this.frames == this.frame){ + this.fireEvent('complete', this.subject); + if (!this.callChain()) this.fireEvent('chainComplete', this.subject); + } else { + this.fireEvent('stop', this.subject); + } + } + return this; + }, + + cancel: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + this.frame = this.frames; + this.fireEvent('cancel', this.subject).clearChain(); + } + return this; + }, + + pause: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + } + return this; + }, + + resume: function(){ + if (this.isPaused()) pushInstance.call(this, this.options.fps); + return this; + }, + + isRunning: function(){ + var list = instances[this.options.fps]; + return list && list.contains(this); + }, + + isPaused: function(){ + return (this.frame < this.frames) && !this.isRunning(); + } + +}); + +Fx.compute = function(from, to, delta){ + return (to - from) * delta + from; +}; + +Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; + +// global timers + +var instances = {}, timers = {}; + +var loop = function(){ + var now = Date.now(); + for (var i = this.length; i--;){ + var instance = this[i]; + if (instance) instance.step(now); + } +}; + +var pushInstance = function(fps){ + var list = instances[fps] || (instances[fps] = []); + list.push(this); + if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list); +}; + +var pullInstance = function(fps){ + var list = instances[fps]; + if (list){ + list.erase(this); + if (!list.length && timers[fps]){ + delete instances[fps]; + timers[fps] = clearInterval(timers[fps]); + } + } +}; + +})(); + + +/* +--- + +name: Fx.CSS + +description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. + +license: MIT-style license. + +requires: [Fx, Element.Style] + +provides: Fx.CSS + +... +*/ + +Fx.CSS = new Class({ + + Extends: Fx, + + //prepares the base from/to object + + prepare: function(element, property, values){ + values = Array.from(values); + var from = values[0], to = values[1]; + if (to == null){ + to = from; + from = element.getStyle(property); + var unit = this.options.unit; + // adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299 + if (unit && from && typeof from == 'string' && from.slice(-unit.length) != unit && parseFloat(from) != 0){ + element.setStyle(property, to + unit); + var value = element.getComputedStyle(property); + // IE and Opera support pixelLeft or pixelWidth + if (!(/px$/.test(value))){ + value = element.style[('pixel-' + property).camelCase()]; + if (value == null){ + // adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + var left = element.style.left; + element.style.left = to + unit; + value = element.style.pixelLeft; + element.style.left = left; + } + } + from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0); + element.setStyle(property, from + unit); + } + } + return {from: this.parse(from), to: this.parse(to)}; + }, + + //parses a value into an array + + parse: function(value){ + value = Function.from(value)(); + value = (typeof value == 'string') ? value.split(' ') : Array.from(value); + return value.map(function(val){ + val = String(val); + var found = false; + Object.each(Fx.CSS.Parsers, function(parser, key){ + if (found) return; + var parsed = parser.parse(val); + if (parsed || parsed === 0) found = {value: parsed, parser: parser}; + }); + found = found || {value: val, parser: Fx.CSS.Parsers.String}; + return found; + }); + }, + + //computes by a from and to prepared objects, using their parsers. + + compute: function(from, to, delta){ + var computed = []; + (Math.min(from.length, to.length)).times(function(i){ + computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); + }); + computed.$family = Function.from('fx:css:value'); + return computed; + }, + + //serves the value as settable + + serve: function(value, unit){ + if (typeOf(value) != 'fx:css:value') value = this.parse(value); + var returned = []; + value.each(function(bit){ + returned = returned.concat(bit.parser.serve(bit.value, unit)); + }); + return returned; + }, + + //renders the change to an element + + render: function(element, property, value, unit){ + element.setStyle(property, this.serve(value, unit)); + }, + + //searches inside the page css to find the values for a selector + + search: function(selector){ + if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; + var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); + + var searchStyles = function(rules){ + Array.each(rules, function(rule, i){ + if (rule.media){ + searchStyles(rule.rules || rule.cssRules); + return; + } + if (!rule.style) return; + var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ + return m.toLowerCase(); + }) : null; + if (!selectorText || !selectorTest.test(selectorText)) return; + Object.each(Element.Styles, function(value, style){ + if (!rule.style[style] || Element.ShortStyles[style]) return; + value = String(rule.style[style]); + to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; + }); + }); + }; + + Array.each(document.styleSheets, function(sheet, j){ + var href = sheet.href; + if (href && href.indexOf('://') > -1 && href.indexOf(document.domain) == -1) return; + var rules = sheet.rules || sheet.cssRules; + searchStyles(rules); + }); + return Fx.CSS.Cache[selector] = to; + } + +}); + +Fx.CSS.Cache = {}; + +Fx.CSS.Parsers = { + + Color: { + parse: function(value){ + if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); + return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; + }, + compute: function(from, to, delta){ + return from.map(function(value, i){ + return Math.round(Fx.compute(from[i], to[i], delta)); + }); + }, + serve: function(value){ + return value.map(Number); + } + }, + + Number: { + parse: parseFloat, + compute: Fx.compute, + serve: function(value, unit){ + return (unit) ? value + unit : value; + } + }, + + String: { + parse: Function.from(false), + compute: function(zero, one){ + return one; + }, + serve: function(zero){ + return zero; + } + } + +}; + + + + +/* +--- + +name: Fx.Tween + +description: Formerly Fx.Style, effect to transition any CSS property for an element. + +license: MIT-style license. + +requires: Fx.CSS + +provides: [Fx.Tween, Element.fade, Element.highlight] + +... +*/ + +Fx.Tween = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(property, now){ + if (arguments.length == 1){ + now = property; + property = this.property || this.options.property; + } + this.render(this.element, property, now, this.options.unit); + return this; + }, + + start: function(property, from, to){ + if (!this.check(property, from, to)) return this; + var args = Array.flatten(arguments); + this.property = this.options.property || args.shift(); + var parsed = this.prepare(this.element, this.property, args); + return this.parent(parsed.from, parsed.to); + } + +}); + +Element.Properties.tween = { + + set: function(options){ + this.get('tween').cancel().setOptions(options); + return this; + }, + + get: function(){ + var tween = this.retrieve('tween'); + if (!tween){ + tween = new Fx.Tween(this, {link: 'cancel'}); + this.store('tween', tween); + } + return tween; + } + +}; + +Element.implement({ + + tween: function(property, from, to){ + this.get('tween').start(property, from, to); + return this; + }, + + fade: function(how){ + var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle; + if (args[1] == null) args[1] = 'toggle'; + switch (args[1]){ + case 'in': method = 'start'; args[1] = 1; break; + case 'out': method = 'start'; args[1] = 0; break; + case 'show': method = 'set'; args[1] = 1; break; + case 'hide': method = 'set'; args[1] = 0; break; + case 'toggle': + var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1); + method = 'start'; + args[1] = flag ? 0 : 1; + this.store('fade:flag', !flag); + toggle = true; + break; + default: method = 'start'; + } + if (!toggle) this.eliminate('fade:flag'); + fade[method].apply(fade, args); + var to = args[args.length - 1]; + if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible'); + else fade.chain(function(){ + this.element.setStyle('visibility', 'hidden'); + this.callChain(); + }); + return this; + }, + + highlight: function(start, end){ + if (!end){ + end = this.retrieve('highlight:original', this.getStyle('background-color')); + end = (end == 'transparent') ? '#fff' : end; + } + var tween = this.get('tween'); + tween.start('background-color', start || '#ffff88', end).chain(function(){ + this.setStyle('background-color', this.retrieve('highlight:original')); + tween.callChain(); + }.bind(this)); + return this; + } + +}); + + +/* +--- + +name: Fx.Morph + +description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. + +license: MIT-style license. + +requires: Fx.CSS + +provides: Fx.Morph + +... +*/ + +Fx.Morph = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(now){ + if (typeof now == 'string') now = this.search(now); + for (var p in now) this.render(this.element, p, now[p], this.options.unit); + return this; + }, + + compute: function(from, to, delta){ + var now = {}; + for (var p in from) now[p] = this.parent(from[p], to[p], delta); + return now; + }, + + start: function(properties){ + if (!this.check(properties)) return this; + if (typeof properties == 'string') properties = this.search(properties); + var from = {}, to = {}; + for (var p in properties){ + var parsed = this.prepare(this.element, p, properties[p]); + from[p] = parsed.from; + to[p] = parsed.to; + } + return this.parent(from, to); + } + +}); + +Element.Properties.morph = { + + set: function(options){ + this.get('morph').cancel().setOptions(options); + return this; + }, + + get: function(){ + var morph = this.retrieve('morph'); + if (!morph){ + morph = new Fx.Morph(this, {link: 'cancel'}); + this.store('morph', morph); + } + return morph; + } + +}; + +Element.implement({ + + morph: function(props){ + this.get('morph').start(props); + return this; + } + +}); + + +/* +--- + +name: Fx.Transitions + +description: Contains a set of advanced transitions to be used with any of the Fx Classes. + +license: MIT-style license. + +credits: + - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. + +requires: Fx + +provides: Fx.Transitions + +... +*/ + +Fx.implement({ + + getTransition: function(){ + var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; + if (typeof trans == 'string'){ + var data = trans.split(':'); + trans = Fx.Transitions; + trans = trans[data[0]] || trans[data[0].capitalize()]; + if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; + } + return trans; + } + +}); + +Fx.Transition = function(transition, params){ + params = Array.from(params); + var easeIn = function(pos){ + return transition(pos, params); + }; + return Object.append(easeIn, { + easeIn: easeIn, + easeOut: function(pos){ + return 1 - transition(1 - pos, params); + }, + easeInOut: function(pos){ + return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2; + } + }); +}; + +Fx.Transitions = { + + linear: function(zero){ + return zero; + } + +}; + + + +Fx.Transitions.extend = function(transitions){ + for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); +}; + +Fx.Transitions.extend({ + + Pow: function(p, x){ + return Math.pow(p, x && x[0] || 6); + }, + + Expo: function(p){ + return Math.pow(2, 8 * (p - 1)); + }, + + Circ: function(p){ + return 1 - Math.sin(Math.acos(p)); + }, + + Sine: function(p){ + return 1 - Math.cos(p * Math.PI / 2); + }, + + Back: function(p, x){ + x = x && x[0] || 1.618; + return Math.pow(p, 2) * ((x + 1) * p - x); + }, + + Bounce: function(p){ + var value; + for (var a = 0, b = 1; 1; a += b, b /= 2){ + if (p >= (7 - 4 * a) / 11){ + value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); + break; + } + } + return value; + }, + + Elastic: function(p, x){ + return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3); + } + +}); + +['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ + Fx.Transitions[transition] = new Fx.Transition(function(p){ + return Math.pow(p, i + 2); + }); +}); + + +/* +--- + +name: Request + +description: Powerful all purpose Request Class. Uses XMLHTTPRequest. + +license: MIT-style license. + +requires: [Object, Element, Chain, Events, Options, Browser] + +provides: Request + +... +*/ + +(function(){ + +var empty = function(){}, + progressSupport = ('onprogress' in new Browser.Request); + +var Request = this.Request = new Class({ + + Implements: [Chain, Events, Options], + + options: {/* + onRequest: function(){}, + onLoadstart: function(event, xhr){}, + onProgress: function(event, xhr){}, + onComplete: function(){}, + onCancel: function(){}, + onSuccess: function(responseText, responseXML){}, + onFailure: function(xhr){}, + onException: function(headerName, value){}, + onTimeout: function(){}, + user: '', + password: '',*/ + url: '', + data: '', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }, + async: true, + format: false, + method: 'post', + link: 'ignore', + isSuccess: null, + emulation: true, + urlEncoded: true, + encoding: 'utf-8', + evalScripts: false, + evalResponse: false, + timeout: 0, + noCache: false + }, + + initialize: function(options){ + this.xhr = new Browser.Request(); + this.setOptions(options); + this.headers = this.options.headers; + }, + + onStateChange: function(){ + var xhr = this.xhr; + if (xhr.readyState != 4 || !this.running) return; + this.running = false; + this.status = 0; + Function.attempt(function(){ + var status = xhr.status; + this.status = (status == 1223) ? 204 : status; + }.bind(this)); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + clearTimeout(this.timer); + + this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; + if (this.options.isSuccess.call(this, this.status)) + this.success(this.response.text, this.response.xml); + else + this.failure(); + }, + + isSuccess: function(){ + var status = this.status; + return (status >= 200 && status < 300); + }, + + isRunning: function(){ + return !!this.running; + }, + + processScripts: function(text){ + if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text); + return text.stripScripts(this.options.evalScripts); + }, + + success: function(text, xml){ + this.onSuccess(this.processScripts(text), xml); + }, + + onSuccess: function(){ + this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); + }, + + failure: function(){ + this.onFailure(); + }, + + onFailure: function(){ + this.fireEvent('complete').fireEvent('failure', this.xhr); + }, + + loadstart: function(event){ + this.fireEvent('loadstart', [event, this.xhr]); + }, + + progress: function(event){ + this.fireEvent('progress', [event, this.xhr]); + }, + + timeout: function(){ + this.fireEvent('timeout', this.xhr); + }, + + setHeader: function(name, value){ + this.headers[name] = value; + return this; + }, + + getHeader: function(name){ + return Function.attempt(function(){ + return this.xhr.getResponseHeader(name); + }.bind(this)); + }, + + check: function(){ + if (!this.running) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + send: function(options){ + if (!this.check(options)) return this; + + this.options.isSuccess = this.options.isSuccess || this.isSuccess; + this.running = true; + + var type = typeOf(options); + if (type == 'string' || type == 'element') options = {data: options}; + + var old = this.options; + options = Object.append({data: old.data, url: old.url, method: old.method}, options); + var data = options.data, url = String(options.url), method = options.method.toLowerCase(); + + switch (typeOf(data)){ + case 'element': data = document.id(data).toQueryString(); break; + case 'object': case 'hash': data = Object.toQueryString(data); + } + + if (this.options.format){ + var format = 'format=' + this.options.format; + data = (data) ? format + '&' + data : format; + } + + if (this.options.emulation && !['get', 'post'].contains(method)){ + var _method = '_method=' + method; + data = (data) ? _method + '&' + data : _method; + method = 'post'; + } + + if (this.options.urlEncoded && ['post', 'put'].contains(method)){ + var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; + this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; + } + + if (!url) url = document.location.pathname; + + var trimPosition = url.lastIndexOf('/'); + if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); + + if (this.options.noCache) + url += (url.indexOf('?') > -1 ? '&' : '?') + String.uniqueID(); + + if (data && (method == 'get' || method == 'delete')){ + url += (url.indexOf('?') > -1 ? '&' : '?') + data; + data = null; + } + + var xhr = this.xhr; + if (progressSupport){ + xhr.onloadstart = this.loadstart.bind(this); + xhr.onprogress = this.progress.bind(this); + } + + xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); + if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; + + xhr.onreadystatechange = this.onStateChange.bind(this); + + Object.each(this.headers, function(value, key){ + try { + xhr.setRequestHeader(key, value); + } catch (e){ + this.fireEvent('exception', [key, value]); + } + }, this); + + this.fireEvent('request'); + xhr.send(data); + if (!this.options.async) this.onStateChange(); + else if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this); + return this; + }, + + cancel: function(){ + if (!this.running) return this; + this.running = false; + var xhr = this.xhr; + xhr.abort(); + clearTimeout(this.timer); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + this.xhr = new Browser.Request(); + this.fireEvent('cancel'); + return this; + } + +}); + +var methods = {}; +['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ + methods[method] = function(data){ + var object = { + method: method + }; + if (data != null) object.data = data; + return this.send(object); + }; +}); + +Request.implement(methods); + +Element.Properties.send = { + + set: function(options){ + var send = this.get('send').cancel(); + send.setOptions(options); + return this; + }, + + get: function(){ + var send = this.retrieve('send'); + if (!send){ + send = new Request({ + data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') + }); + this.store('send', send); + } + return send; + } + +}; + +Element.implement({ + + send: function(url){ + var sender = this.get('send'); + sender.send({data: this, url: url || sender.options.url}); + return this; + } + +}); + +})(); + + +/* +--- + +name: Request.HTML + +description: Extends the basic Request Class with additional methods for interacting with HTML responses. + +license: MIT-style license. + +requires: [Element, Request] + +provides: Request.HTML + +... +*/ + +Request.HTML = new Class({ + + Extends: Request, + + options: { + update: false, + append: false, + evalScripts: true, + filter: false, + headers: { + Accept: 'text/html, application/xml, text/xml, */*' + } + }, + + success: function(text){ + var options = this.options, response = this.response; + + response.html = text.stripScripts(function(script){ + response.javascript = script; + }); + + var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); + if (match) response.html = match[1]; + var temp = new Element('div').set('html', response.html); + + response.tree = temp.childNodes; + response.elements = temp.getElements(options.filter || '*'); + + if (options.filter) response.tree = response.elements; + if (options.update){ + var update = document.id(options.update).empty(); + if (options.filter) update.adopt(response.elements); + else update.set('html', response.html); + } else if (options.append){ + var append = document.id(options.append); + if (options.filter) response.elements.reverse().inject(append); + else append.adopt(temp.getChildren()); + } + if (options.evalScripts) Browser.exec(response.javascript); + + this.onSuccess(response.tree, response.elements, response.html, response.javascript); + } + +}); + +Element.Properties.load = { + + set: function(options){ + var load = this.get('load').cancel(); + load.setOptions(options); + return this; + }, + + get: function(){ + var load = this.retrieve('load'); + if (!load){ + load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'}); + this.store('load', load); + } + return load; + } + +}; + +Element.implement({ + + load: function(){ + this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString})); + return this; + } + +}); + + +/* +--- + +name: JSON + +description: JSON encoder and decoder. + +license: MIT-style license. + +SeeAlso: <http://www.json.org/> + +requires: [Array, String, Number, Function] + +provides: JSON + +... +*/ + +if (typeof JSON == 'undefined') this.JSON = {}; + + + +(function(){ + +var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; + +var escape = function(chr){ + return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); +}; + +JSON.validate = function(string){ + string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''); + + return (/^[\],:{}\s]*$/).test(string); +}; + +JSON.encode = JSON.stringify ? function(obj){ + return JSON.stringify(obj); +} : function(obj){ + if (obj && obj.toJSON) obj = obj.toJSON(); + + switch (typeOf(obj)){ + case 'string': + return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; + case 'array': + return '[' + obj.map(JSON.encode).clean() + ']'; + case 'object': case 'hash': + var string = []; + Object.each(obj, function(value, key){ + var json = JSON.encode(value); + if (json) string.push(JSON.encode(key) + ':' + json); + }); + return '{' + string + '}'; + case 'number': case 'boolean': return '' + obj; + case 'null': return 'null'; + } + + return null; +}; + +JSON.secure = true; + + +JSON.decode = function(string, secure){ + if (!string || typeOf(string) != 'string') return null; + + if (secure == null) secure = JSON.secure; + if (secure){ + if (JSON.parse) return JSON.parse(string); + if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); + } + + return eval('(' + string + ')'); +}; + +})(); + + +/* +--- + +name: Request.JSON + +description: Extends the basic Request Class with additional methods for sending and receiving JSON data. + +license: MIT-style license. + +requires: [Request, JSON] + +provides: Request.JSON + +... +*/ + +Request.JSON = new Class({ + + Extends: Request, + + options: { + /*onError: function(text, error){},*/ + secure: true + }, + + initialize: function(options){ + this.parent(options); + Object.append(this.headers, { + 'Accept': 'application/json', + 'X-Request': 'JSON' + }); + }, + + success: function(text){ + var json; + try { + json = this.response.json = JSON.decode(text, this.options.secure); + } catch (error){ + this.fireEvent('error', [text, error]); + return; + } + if (json == null) this.onFailure(); + else this.onSuccess(json, text); + } + +}); + + +/* +--- + +name: Cookie + +description: Class for creating, reading, and deleting browser Cookies. + +license: MIT-style license. + +credits: + - Based on the functions by Peter-Paul Koch (http://quirksmode.org). + +requires: [Options, Browser] + +provides: Cookie + +... +*/ + +var Cookie = new Class({ + + Implements: Options, + + options: { + path: '/', + domain: false, + duration: false, + secure: false, + document: document, + encode: true + }, + + initialize: function(key, options){ + this.key = key; + this.setOptions(options); + }, + + write: function(value){ + if (this.options.encode) value = encodeURIComponent(value); + if (this.options.domain) value += '; domain=' + this.options.domain; + if (this.options.path) value += '; path=' + this.options.path; + if (this.options.duration){ + var date = new Date(); + date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); + value += '; expires=' + date.toGMTString(); + } + if (this.options.secure) value += '; secure'; + this.options.document.cookie = this.key + '=' + value; + return this; + }, + + read: function(){ + var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); + return (value) ? decodeURIComponent(value[1]) : null; + }, + + dispose: function(){ + new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write(''); + return this; + } + +}); + +Cookie.write = function(key, value, options){ + return new Cookie(key, options).write(value); +}; + +Cookie.read = function(key){ + return new Cookie(key).read(); +}; + +Cookie.dispose = function(key, options){ + return new Cookie(key, options).dispose(); +}; + + +/* +--- + +name: DOMReady + +description: Contains the custom event domready. + +license: MIT-style license. + +requires: [Browser, Element, Element.Event] + +provides: [DOMReady, DomReady] + +... +*/ + +(function(window, document){ + +var ready, + loaded, + checks = [], + shouldPoll, + timer, + testElement = document.createElement('div'); + +var domready = function(){ + clearTimeout(timer); + if (ready) return; + Browser.loaded = ready = true; + document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); + + document.fireEvent('domready'); + window.fireEvent('domready'); +}; + +var check = function(){ + for (var i = checks.length; i--;) if (checks[i]()){ + domready(); + return true; + } + return false; +}; + +var poll = function(){ + clearTimeout(timer); + if (!check()) timer = setTimeout(poll, 10); +}; + +document.addListener('DOMContentLoaded', domready); + +/*<ltIE8>*/ +// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/ +// testElement.doScroll() throws when the DOM is not ready, only in the top window +var doScrollWorks = function(){ + try { + testElement.doScroll(); + return true; + } catch (e){} + return false; +}; +// If doScroll works already, it can't be used to determine domready +// e.g. in an iframe +if (testElement.doScroll && !doScrollWorks()){ + checks.push(doScrollWorks); + shouldPoll = true; +} +/*</ltIE8>*/ + +if (document.readyState) checks.push(function(){ + var state = document.readyState; + return (state == 'loaded' || state == 'complete'); +}); + +if ('onreadystatechange' in document) document.addListener('readystatechange', check); +else shouldPoll = true; + +if (shouldPoll) poll(); + +Element.Events.domready = { + onAdd: function(fn){ + if (ready) fn.call(this); + } +}; + +// Make sure that domready fires before load +Element.Events.load = { + base: 'load', + onAdd: function(fn){ + if (loaded && this == window) fn.call(this); + }, + condition: function(){ + if (this == window){ + domready(); + delete Element.Events.load; + } + return true; + } +}; + +// This is based on the custom load event +window.addEvent('load', function(){ + loaded = true; +}); + +})(window, document); + diff --git a/module/webui/themes/default/js/static/mootools-core.min.js b/module/webui/themes/default/js/static/mootools-core.min.js new file mode 100644 index 000000000..354f94196 --- /dev/null +++ b/module/webui/themes/default/js/static/mootools-core.min.js @@ -0,0 +1,491 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/core/8423c12ffd6a6bfcde9ea22554aec795 + +packager build: + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady + +copyrights: + - [MooTools](http://mootools.net) + +licenses: + - [MIT License](http://mootools.net/license.txt) +... +*/ + +(function(){this.MooTools={version:"1.5.0",build:"0f7b690afee9349b15909f33016a25d2e4d9f4e3"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family!=null){return i.$family(); +}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if("callee" in i){return"arguments"; +}if("item" in i){return"collection";}}}return typeof i;};var j=this.instanceOf=function(t,i){if(t==null){return false;}var s=t.$constructor||t.constructor; +while(s){if(s===i){return true;}s=s.parent;}if(!t.hasOwnProperty){return false;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null; +}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];}f.prototype.overloadSetter=function(s){var i=this; +return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]);}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]); +}}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this;return function(u){var v,t;if(typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments; +}else{if(s){v=[u];}}}if(v){t={};for(var w=0;w<v.length;w++){t[v[w]]=i.call(this,v[w]);}}else{t=i.call(this,u);}return t;};};f.prototype.extend=function(i,s){this[i]=s; +}.overloadSetter();f.prototype.implement=function(i,s){this.prototype[i]=s;}.overloadSetter();var n=Array.prototype.slice;f.from=function(i){return(o(i)=="function")?i:function(){return i; +};};Array.from=function(i){if(i==null){return[];}return(a.isEnumerable(i)&&typeof i!="string")?(o(i)=="array")?i:n.call(i):[i];};Number.from=function(s){var i=parseFloat(s); +return isFinite(i)?i:null;};String.from=function(i){return i+"";};f.implement({hide:function(){this.$hidden=true;return this;},protect:function(){this.$protected=true; +return this;}});var a=this.Type=function(u,t){if(u){var s=u.toLowerCase();var i=function(v){return(o(v)==s);};a["is"+u]=i;if(t!=null){t.prototype.$family=(function(){return s; +}).hide();}}if(t==null){return null;}t.extend(this);t.$constructor=a;t.prototype.$constructor=t;return t;};var e=Object.prototype.toString;a.isEnumerable=function(i){return(i!=null&&typeof i.length=="number"&&e.call(i)!="[object Function]"); +};var q={};var r=function(i){var s=o(i.prototype);return q[s]||(q[s]=[]);};var b=function(t,x){if(x&&x.$hidden){return;}var s=r(this);for(var u=0;u<s.length; +u++){var w=s[u];if(o(w)=="type"){b.call(w,t,x);}else{w.call(this,t,x);}}var v=this.prototype[t];if(v==null||!v.$protected){this.prototype[t]=x;}if(this[t]==null&&o(x)=="function"){m.call(this,t,function(i){return x.apply(i,n.call(arguments,1)); +});}};var m=function(i,t){if(t&&t.$hidden){return;}var s=this[i];if(s==null||!s.$protected){this[i]=t;}};a.implement({implement:b.overloadSetter(),extend:m.overloadSetter(),alias:function(i,s){b.call(this,i,this.prototype[s]); +}.overloadSetter(),mirror:function(i){r(this).push(i);return this;}});new a("Type",a);var d=function(s,x,v){var u=(x!=Object),B=x.prototype;if(u){x=new a(s,x); +}for(var y=0,w=v.length;y<w;y++){var C=v[y],A=x[C],z=B[C];if(A){A.protect();}if(u&&z){x.implement(C,z.protect());}}if(u){var t=B.propertyIsEnumerable(v[0]); +x.forEachMethod=function(G){if(!t){for(var F=0,D=v.length;F<D;F++){G.call(B,B[v[F]],v[F]);}}for(var E in B){G.call(B,B[E],E);}};}return d;};d("String",String,["charAt","charCodeAt","concat","contains","indexOf","lastIndexOf","match","quote","replace","search","slice","split","substr","substring","trim","toLowerCase","toUpperCase"])("Array",Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"])("Number",Number,["toExponential","toFixed","toLocaleString","toPrecision"])("Function",f,["apply","call","bind"])("RegExp",RegExp,["exec","test"])("Object",Object,["create","defineProperty","defineProperties","keys","getPrototypeOf","getOwnPropertyDescriptor","getOwnPropertyNames","preventExtensions","isExtensible","seal","isSealed","freeze","isFrozen"])("Date",Date,["now"]); +Object.extend=m.overloadSetter();Date.extend("now",function(){return +(new Date);});new a("Boolean",Boolean);Number.prototype.$family=function(){return isFinite(this)?"number":"null"; +}.hide();Number.extend("random",function(s,i){return Math.floor(Math.random()*(i-s+1)+s);});var g=Object.prototype.hasOwnProperty;Object.extend("forEach",function(i,t,u){for(var s in i){if(g.call(i,s)){t.call(u,i[s],s,i); +}}});Object.each=Object.forEach;Array.implement({forEach:function(u,v){for(var t=0,s=this.length;t<s;t++){if(t in this){u.call(v,this[t],t,this);}}},each:function(i,s){Array.forEach(this,i,s); +return this;}});var l=function(i){switch(o(i)){case"array":return i.clone();case"object":return Object.clone(i);default:return i;}};Array.implement("clone",function(){var s=this.length,t=new Array(s); +while(s--){t[s]=l(this[s]);}return t;});var h=function(s,i,t){switch(o(t)){case"object":if(o(s[i])=="object"){Object.merge(s[i],t);}else{s[i]=Object.clone(t); +}break;case"array":s[i]=t.clone();break;default:s[i]=t;}return s;};Object.extend({merge:function(z,u,t){if(o(u)=="string"){return h(z,u,t);}for(var y=1,s=arguments.length; +y<s;y++){var w=arguments[y];for(var x in w){h(z,x,w[x]);}}return z;},clone:function(i){var t={};for(var s in i){t[s]=l(i[s]);}return t;},append:function(w){for(var v=1,t=arguments.length; +v<t;v++){var s=arguments[v]||{};for(var u in s){w[u]=s[u];}}return w;}});["Object","WhiteSpace","TextNode","Collection","Arguments"].each(function(i){new a(i); +});var c=Date.now();String.extend("uniqueID",function(){return(c++).toString(36);});})();Array.implement({every:function(c,d){for(var b=0,a=this.length>>>0; +b<a;b++){if((b in this)&&!c.call(d,this[b],b,this)){return false;}}return true;},filter:function(d,f){var c=[];for(var e,b=0,a=this.length>>>0;b<a;b++){if(b in this){e=this[b]; +if(d.call(f,e,b,this)){c.push(e);}}}return c;},indexOf:function(c,d){var b=this.length>>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a<b;a++){if(this[a]===c){return a; +}}return -1;},map:function(c,e){var d=this.length>>>0,b=Array(d);for(var a=0;a<d;a++){if(a in this){b[a]=c.call(e,this[a],a,this);}}return b;},some:function(c,d){for(var b=0,a=this.length>>>0; +b<a;b++){if((b in this)&&c.call(d,this[b],b,this)){return true;}}return false;},clean:function(){return this.filter(function(a){return a!=null;});},invoke:function(a){var b=Array.slice(arguments,1); +return this.map(function(c){return c[a].apply(c,b);});},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a]; +}return d;},link:function(c){var a={};for(var e=0,b=this.length;e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1; +},append:function(a){this.push.apply(this,a);return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[Number.random(0,this.length-1)]:null; +},include:function(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this; +},erase:function(b){for(var a=this.length;a--;){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[]; +for(var b=0,a=this.length;b<a;b++){var c=typeOf(this[b]);if(c=="null"){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments"||instanceOf(this[b],Array))?Array.flatten(this[b]):this[b]); +}return d;},pick:function(){for(var b=0,a=this.length;b<a;b++){if(this[b]!=null){return this[b];}}return null;},hexToRgb:function(b){if(this.length!=3){return null; +}var a=this.map(function(c){if(c.length==1){c+=c;}return parseInt(c,16);});return(b)?a:"rgb("+a+")";},rgbToHex:function(d){if(this.length<3){return null; +}if(this.length==4&&this[3]==0&&!d){return"transparent";}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join(""); +}});String.implement({contains:function(b,a){return(a?String(this).slice(a):String(this)).indexOf(b)>-1;},test:function(a,b){return((typeOf(a)=="regexp")?a:new RegExp(""+a,b)).test(this); +},trim:function(){return String(this).replace(/^\s+|\s+$/g,"");},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase(); +});},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase(); +});},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this); +},hexToRgb:function(b){var a=String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g); +return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return String(this).replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1); +}return(a[c]!=null)?a[c]:"";});}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0).toFixed(a<0?-a:0); +return Math.round(this*a)/a;},times:function(b,c){for(var a=0;a<this;a++){b.call(c,a,this);}},toFloat:function(){return parseFloat(this);},toInt:function(a){return parseInt(this,a||10); +}});Number.alias("each","times");(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat(Array.from(arguments))); +};}});Number.implement(a);})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);Function.extend({attempt:function(){for(var b=0,a=arguments.length; +b<a;b++){try{return arguments[b]();}catch(c){}}return null;}});Function.implement({attempt:function(a,c){try{return this.apply(c,Array.from(a));}catch(b){}return null; +},bind:function(e){var a=this,b=arguments.length>1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype; +g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;},pass:function(b,c){var a=this; +if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b); +},periodical:function(c,b,a){return setInterval(this.pass((a==null?[]:a),b),c);}});(function(){var a=Object.prototype.hasOwnProperty;Object.extend({subset:function(d,g){var f={}; +for(var e=0,b=g.length;e<b;e++){var c=g[e];if(c in d){f[c]=d[c];}}return f;},map:function(b,e,f){var d={};for(var c in b){if(a.call(b,c)){d[c]=e.call(f,b[c],c,b); +}}return d;},filter:function(b,e,g){var d={};for(var c in b){var f=b[c];if(a.call(b,c)&&e.call(g,f,c,b)){d[c]=f;}}return d;},every:function(b,d,e){for(var c in b){if(a.call(b,c)&&!d.call(e,b[c],c)){return false; +}}return true;},some:function(b,d,e){for(var c in b){if(a.call(b,c)&&d.call(e,b[c],c)){return true;}}return false;},keys:function(b){var d=[];for(var c in b){if(a.call(b,c)){d.push(c); +}}return d;},values:function(c){var b=[];for(var d in c){if(a.call(c,d)){b.push(c[d]);}}return b;},getLength:function(b){return Object.keys(b).length;},keyOf:function(b,d){for(var c in b){if(a.call(b,c)&&b[c]===d){return c; +}}return null;},contains:function(b,c){return Object.keyOf(b,c)!=null;},toQueryString:function(b,c){var d=[];Object.each(b,function(h,g){if(c){g=c+"["+g+"]"; +}var f;switch(typeOf(h)){case"object":f=Object.toQueryString(h,g);break;case"array":var e={};h.each(function(k,j){e[j]=k;});f=Object.toQueryString(e,g); +break;default:f=g+"="+encodeURIComponent(h);}if(h!=null){d.push(f);}});return d.join("&");}});})();(function(){var f=this.document;var d=f.window=this; +var a=function(k,e){k=k.toLowerCase();e=(e?e.toLowerCase():"");var l=k.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/)||[null,"unknown",0]; +if(l[1]=="trident"){l[1]="ie";if(l[4]){l[2]=l[4];}}else{if(l[1]=="crios"){l[1]="chrome";}}var e=k.match(/ip(?:ad|od|hone)/)?"ios":(k.match(/(?:webos|android)/)||e.match(/mac|win|linux/)||["other"])[0]; +if(e=="win"){e="windows";}return{extend:Function.prototype.extend,name:(l[1]=="version")?l[3]:l[1],version:parseFloat((l[1]=="opera"&&l[4])?l[4]:l[2]),platform:e}; +};var j=this.Browser=a(navigator.userAgent,navigator.platform);if(j.ie){j.version=f.documentMode;}j.extend({Features:{xpath:!!(f.evaluate),air:!!(d.runtime),query:!!(f.querySelector),json:!!(d.JSON)},parseUA:a}); +j.Request=(function(){var l=function(){return new XMLHttpRequest();};var k=function(){return new ActiveXObject("MSXML2.XMLHTTP");};var e=function(){return new ActiveXObject("Microsoft.XMLHTTP"); +};return Function.attempt(function(){l();return l;},function(){k();return k;},function(){e();return e;});})();j.Features.xhr=!!(j.Request);j.exec=function(k){if(!k){return k; +}if(d.execScript){d.execScript(k);}else{var e=f.createElement("script");e.setAttribute("type","text/javascript");e.text=k;f.head.appendChild(e);f.head.removeChild(e); +}return k;};String.implement("stripScripts",function(k){var e="";var l=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(m,n){e+=n+"\n";return""; +});if(k===true){j.exec(e);}else{if(typeOf(k)=="function"){k(e,l);}}return l;});j.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event}); +this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,k){d[e]=k;});this.Document=f.$constructor=new Type("Document",function(){}); +f.$family=Function.from("document").hide();Document.mirror(function(e,k){f[e]=k;});f.html=f.documentElement;if(!f.head){f.head=f.getElementsByTagName("head")[0]; +}if(f.execCommand){try{f.execCommand("BackgroundImageCache",false,true);}catch(c){}}if(this.attachEvent&&!this.addEventListener){var b=function(){this.detachEvent("onunload",b); +f.head=f.html=f.window=null;};this.attachEvent("onunload",b);}var g=Array.from;try{g(f.html.childNodes);}catch(c){Array.from=function(k){if(typeof k!="string"&&Type.isEnumerable(k)&&typeOf(k)!="array"){var e=k.length,l=new Array(e); +while(e--){l[e]=k[e];}return l;}return g(k);};var h=Array.prototype,i=h.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var k=h[e]; +Array[e]=function(l){return k.apply(Array.from(l),i.call(arguments,1));};});}})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window; +}c=c||g.event;if(c.$extended){return c;}this.event=c;this.$extended=true;this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey; +var i=this.type=c.type;var h=c.target||c.srcElement;while(h&&h.nodeType==3){h=h.parentNode;}this.target=document.id(h);if(i.indexOf("key")==0){var d=this.code=(c.which||c.keyCode); +this.key=b[d];if(i=="keydown"||i=="keyup"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase(); +}}else{if(i=="click"||i=="dblclick"||i=="contextmenu"||i=="DOMMouseScroll"||i.indexOf("mouse")==0){var j=g.document;j=(!j.compatMode||j.compatMode=="CSS1Compat")?j.html:j.body; +this.page={x:(c.pageX!=null)?c.pageX:c.clientX+j.scrollLeft,y:(c.pageY!=null)?c.pageY:c.clientY+j.scrollTop};this.client={x:(c.pageX!=null)?c.pageX-g.pageXOffset:c.clientX,y:(c.pageY!=null)?c.pageY-g.pageYOffset:c.clientY}; +if(i=="DOMMouseScroll"||i=="mousewheel"){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3;}this.rightClick=(c.which==3||c.button==2);if(i=="mouseover"||i=="mouseout"){var k=c.relatedTarget||c[(i=="mouseover"?"from":"to")+"Element"]; +while(k&&k.nodeType==3){k=k.parentNode;}this.relatedTarget=document.id(k);}}else{if(i.indexOf("touch")==0||i.indexOf("gesture")==0){this.rotation=c.rotation; +this.scale=c.scale;this.targetTouches=c.targetTouches;this.changedTouches=c.changedTouches;var f=this.touches=c.touches;if(f&&f[0]){var e=f[0];this.page={x:e.pageX,y:e.pageY}; +this.client={x:e.clientX,y:e.clientY};}}}}if(!this.client){this.client={};}if(!this.page){this.page={};}});a.implement({stop:function(){return this.preventDefault().stopPropagation(); +},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault(); +}else{this.event.returnValue=false;}return this;}});a.defineKey=function(d,c){b[d]=c;return this;};a.defineKeys=a.defineKey.overloadSetter(true);a.defineKeys({"38":"up","40":"down","37":"left","39":"right","27":"esc","32":"space","8":"backspace","9":"tab","46":"delete","13":"enter"}); +})();(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h};}var g=function(){e(this);if(g.$prototyping){return this; +}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null;return i;}.extend(this).implement(h); +g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.'); +}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments); +};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone(); +break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.'); +}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h}); +return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this; +}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping; +return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j; +for(var i in h){f.call(this,i,h[i],true);}},this);}};})();(function(){this.Chain=new Class({$chain:[],chain:function(){this.$chain.append(Array.flatten(arguments)); +return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){this.$chain.empty(); +return this;}});var a=function(b){return b.replace(/^on([A-Z])/,function(c,d){return d.toLowerCase();});};this.Events=new Class({$events:{},addEvent:function(d,c,b){d=a(d); +this.$events[d]=(this.$events[d]||[]).include(c);if(b){c.internal=true;}return this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this; +},fireEvent:function(e,c,b){e=a(e);var d=this.$events[e];if(!d){return this;}c=Array.from(c);d.each(function(f){if(b){f.delay(b,this,c);}else{f.apply(this,c); +}},this);return this;},removeEvent:function(e,d){e=a(e);var c=this.$events[e];if(c&&!d.internal){var b=c.indexOf(d);if(b!=-1){delete c[b];}}return this; +},removeEvents:function(d){var e;if(typeOf(d)=="object"){for(e in d){this.removeEvent(e,d[e]);}return this;}if(d){d=a(d);}for(e in this.$events){if(d&&d!=e){continue; +}var c=this.$events[e];for(var b=c.length;b--;){if(b in c){this.removeEvent(e,c[b]);}}}return this;}});this.Options=new Class({setOptions:function(){var b=this.options=Object.merge.apply(null,[{},this.options].append(arguments)); +if(this.addEvent){for(var c in b){if(typeOf(b[c])!="function"||!(/^on[A-Z]/).test(c)){continue;}this.addEvent(c,b[c]);delete b[c];}}return this;}});})(); +(function(){var k,n,l,g,a={},c={},m=/\\/g;var e=function(q,p){if(q==null){return null;}if(q.Slick===true){return q;}q=(""+q).replace(/^\s+|\s+$/g,"");g=!!p; +var o=(g)?c:a;if(o[q]){return o[q];}k={Slick:true,expressions:[],raw:q,reverse:function(){return e(this.raw,true);}};n=-1;while(q!=(q=q.replace(j,b))){}k.length=k.expressions.length; +return o[k.raw]=(g)?h(k):k;};var i=function(o){if(o==="!"){return" ";}else{if(o===" "){return"!";}else{if((/^!/).test(o)){return o.replace(/^!/,"");}else{return"!"+o; +}}}};var h=function(u){var r=u.expressions;for(var p=0;p<r.length;p++){var t=r[p];var q={parts:[],tag:"*",combinator:i(t[0].combinator)};for(var o=0;o<t.length; +o++){var s=t[o];if(!s.reverseCombinator){s.reverseCombinator=" ";}s.combinator=s.reverseCombinator;delete s.reverseCombinator;}t.reverse().push(q);}return u; +};var f=function(o){return o.replace(/[-[\]{}()*+?.\\^$|,#\s]/g,function(p){return"\\"+p;});};var j=new RegExp("^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(/<combinator>/,"["+f(">+~`!@$%^&={}\\;</")+"]").replace(/<unicode>/g,"(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])").replace(/<unicode1>/g,"(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])")); +function b(x,s,D,z,r,C,q,B,A,y,u,F,G,v,p,w){if(s||n===-1){k.expressions[++n]=[];l=-1;if(s){return"";}}if(D||z||l===-1){D=D||" ";var t=k.expressions[n]; +if(g&&t[l]){t[l].reverseCombinator=i(D);}t[++l]={combinator:D,tag:"*"};}var o=k.expressions[n][l];if(r){o.tag=r.replace(m,"");}else{if(C){o.id=C.replace(m,""); +}else{if(q){q=q.replace(m,"");if(!o.classList){o.classList=[];}if(!o.classes){o.classes=[];}o.classList.push(q);o.classes.push({value:q,regexp:new RegExp("(^|\\s)"+f(q)+"(\\s|$)")}); +}else{if(G){w=w||p;w=w?w.replace(m,""):null;if(!o.pseudos){o.pseudos=[];}o.pseudos.push({key:G.replace(m,""),value:w,type:F.length==1?"class":"element"}); +}else{if(B){B=B.replace(m,"");u=(u||"").replace(m,"");var E,H;switch(A){case"^=":H=new RegExp("^"+f(u));break;case"$=":H=new RegExp(f(u)+"$");break;case"~=":H=new RegExp("(^|\\s)"+f(u)+"(\\s|$)"); +break;case"|=":H=new RegExp("^"+f(u)+"(-|$)");break;case"=":E=function(I){return u==I;};break;case"*=":E=function(I){return I&&I.indexOf(u)>-1;};break; +case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}if(u==""&&(/^[*$^]=$/).test(A)){E=function(){return false;};}if(!E){E=function(I){return I&&H.test(I); +};}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o); +};d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var k={},m={},d=Object.prototype.toString; +k.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};k.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(d.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML"); +};k.setDocument=function(w){var p=w.nodeType;if(p==9){}else{if(p){w=w.ownerDocument;}else{if(w.navigator){w=w.document;}else{return;}}}if(this.document===w){return; +}this.document=w;var A=w.documentElement,o=this.getUIDXML(A),s=m[o],r;if(s){for(r in s){this[r]=s[r];}return;}s=m[o]={};s.root=A;s.isXMLDocument=this.isXML(w); +s.brokenStarGEBTN=s.starSelectsClosedQSA=s.idGetsName=s.brokenMixedCaseQSA=s.brokenGEBCN=s.brokenCheckedQSA=s.brokenEmptyAttributeQSA=s.isHTMLDocument=s.nativeMatchesSelector=false; +var q,u,y,z,t;var x,v="slick_uniqueid";var c=w.createElement("div");var n=w.body||w.getElementsByTagName("body")[0]||A;n.appendChild(c);try{c.innerHTML='<a id="'+v+'"></a>'; +s.isHTMLDocument=!!w.getElementById(v);}catch(C){}if(s.isHTMLDocument){c.style.display="none";c.appendChild(w.createComment(""));u=(c.getElementsByTagName("*").length>1); +try{c.innerHTML="foo</foo>";x=c.getElementsByTagName("*");q=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");}catch(C){}s.brokenStarGEBTN=u||q;try{c.innerHTML='<a name="'+v+'"></a><b id="'+v+'"></b>'; +s.idGetsName=w.getElementById(v)===c.firstChild;}catch(C){}if(c.getElementsByClassName){try{c.innerHTML='<a class="f"></a><a class="b"></a>';c.getElementsByClassName("b").length; +c.firstChild.className="b";z=(c.getElementsByClassName("b").length!=2);}catch(C){}try{c.innerHTML='<a class="a"></a><a class="f b a"></a>';y=(c.getElementsByClassName("a").length!=2); +}catch(C){}s.brokenGEBCN=z||y;}if(c.querySelectorAll){try{c.innerHTML="foo</foo>";x=c.querySelectorAll("*");s.starSelectsClosedQSA=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/"); +}catch(C){}try{c.innerHTML='<a class="MiX"></a>';s.brokenMixedCaseQSA=!c.querySelectorAll(".MiX").length;}catch(C){}try{c.innerHTML='<select><option selected="selected">a</option></select>'; +s.brokenCheckedQSA=(c.querySelectorAll(":checked").length==0);}catch(C){}try{c.innerHTML='<a class=""></a>';s.brokenEmptyAttributeQSA=(c.querySelectorAll('[class*=""]').length!=0); +}catch(C){}}try{c.innerHTML='<form action="s"><input id="action"/></form>';t=(c.firstChild.getAttribute("action")!="s");}catch(C){}s.nativeMatchesSelector=A.matches||A.mozMatchesSelector||A.webkitMatchesSelector; +if(s.nativeMatchesSelector){try{s.nativeMatchesSelector.call(A,":slick");s.nativeMatchesSelector=null;}catch(C){}}}try{A.slick_expando=1;delete A.slick_expando; +s.getUID=this.getUIDHTML;}catch(C){s.getUID=this.getUIDXML;}n.removeChild(c);c=x=n=null;s.getAttribute=(s.isHTMLDocument&&t)?function(G,E){var H=this.attributeGetters[E]; +if(H){return H.call(G);}var F=G.getAttributeNode(E);return(F)?F.nodeValue:null;}:function(F,E){var G=this.attributeGetters[E];return(G)?G.call(F):F.getAttribute(E); +};s.hasAttribute=(A&&this.isNativeCode(A.hasAttribute))?function(F,E){return F.hasAttribute(E);}:function(F,E){F=F.getAttributeNode(E);return !!(F&&(F.specified||F.nodeValue)); +};var D=A&&this.isNativeCode(A.contains),B=w&&this.isNativeCode(w.contains);s.contains=(D&&B)?function(E,F){return E.contains(F);}:(D&&!B)?function(E,F){return E===F||((E===w)?w.documentElement:E).contains(F); +}:(A&&A.compareDocumentPosition)?function(E,F){return E===F||!!(E.compareDocumentPosition(F)&16);}:function(E,F){if(F){do{if(F===E){return true;}}while((F=F.parentNode)); +}return false;};s.documentSorter=(A.compareDocumentPosition)?function(F,E){if(!F.compareDocumentPosition||!E.compareDocumentPosition){return 0;}return F.compareDocumentPosition(E)&4?-1:F===E?0:1; +}:("sourceIndex" in A)?function(F,E){if(!F.sourceIndex||!E.sourceIndex){return 0;}return F.sourceIndex-E.sourceIndex;}:(w.createRange)?function(H,F){if(!H.ownerDocument||!F.ownerDocument){return 0; +}var G=H.ownerDocument.createRange(),E=F.ownerDocument.createRange();G.setStart(H,0);G.setEnd(H,0);E.setStart(F,0);E.setEnd(F,0);return G.compareBoundaryPoints(Range.START_TO_END,E); +}:null;A=null;for(r in s){this[r]=s[r];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={};k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]); +if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9);if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U); +}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f);simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors; +}E=U.getElementsByTagName(v);if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors; +}A=U.getElementById(v);if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A); +}}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v); +if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+e.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*"); +for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p); +}return(s)?null:p;}querySelector:if(U.querySelectorAll){if(!this.isHTMLDocument||g[z]||this.brokenMixedCaseQSA||(this.brokenCheckedQSA&&z.indexOf(":checked")>-1)||(this.brokenEmptyAttributeQSA&&h.test(z))||(!y&&z.indexOf(",")>-1)||e.disableQSA){break querySelector; +}var S=z,x=U;if(!y){var C=x.getAttribute("id"),t="slickid__";x.setAttribute("id",t);S="#"+t+" "+S;U=x.parentNode;}try{if(s){return U.querySelector(S)||null; +}else{E=U.querySelectorAll(S);}}catch(Q){g[z]=1;break querySelector;}finally{if(!y){if(C){x.setAttribute("id",C);}else{x.removeAttribute("id");}U=x;}}if(this.starSelectsClosedQSA){for(O=0; +A=E[O++];){if(A.nodeName>"@"&&!(I&&V[this.getUID(A)])){p.push(A);}}}else{for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}if(I){this.sort(p); +}return p;}F=this.Slick.parse(z);if(!F.length){return p;}}else{if(z==null){return p;}else{if(z.Slick){F=z;}else{if(this.contains(U.documentElement||U,z)){(p)?p.push(z):p=z; +return p;}else{return p;}}}}this.posNTH={};this.posNTHLast={};this.posNTHType={};this.posNTHTypeLast={};this.push=(!I&&(s||(F.length==1&&F.expressions[0].length==1)))?this.pushArray:this.pushUID; +if(p==null){p=[];}var M,L,K;var B,J,D,c,q,G,W;var N,P,o,w,R=F.expressions;search:for(O=0;(P=R[O]);O++){for(M=0;(o=P[M]);M++){B="combinator:"+o.combinator; +if(!this[B]){continue search;}J=(this.isXMLDocument)?o.tag:o.tag.toUpperCase();D=o.id;c=o.classList;q=o.classes;G=o.attributes;W=o.pseudos;w=(M===(P.length-1)); +this.bitUniques={};if(w){this.uniques=V;this.found=p;}else{this.uniques={};this.found=[];}if(M===0){this[B](U,J,D,q,G,W,c);if(s&&w&&p.length){break search; +}}else{if(s&&w){for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);if(p.length){break search;}}}else{for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c); +}}}N=this.found;}}if(I||(F.expressions.length>1)){this.sort(p);}return(s)?(p[0]||null):p;};k.uidx=1;k.uidk="slick-uniqueid";k.getUIDXML=function(n){var c=n.getAttribute(this.uidk); +if(!c){c=this.uidx++;n.setAttribute(this.uidk,c);}return c;};k.getUIDHTML=function(c){return c.uniqueNumber||(c.uniqueNumber=this.uidx++);};k.sort=function(c){if(!this.documentSorter){return c; +}c.sort(this.documentSorter);return c;};k.cacheNTH={};k.matchNTH=/^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;k.parseNTHArgument=function(q){var o=q.match(this.matchNTH); +if(!o){return false;}var p=o[2]||false;var n=o[1]||1;if(n=="-"){n=-1;}var c=+o[3]||0;o=(p=="n")?{a:n,b:c}:(p=="odd")?{a:2,b:1}:(p=="even")?{a:2,b:0}:{a:0,b:n}; +return(this.cacheNTH[q]=o);};k.createNTHPseudo=function(p,n,c,o){return function(s,q){var u=this.getUID(s);if(!this[c][u]){var A=s.parentNode;if(!A){return false; +}var r=A[p],t=1;if(o){var z=s.nodeName;do{if(r.nodeName!=z){continue;}this[c][this.getUID(r)]=t++;}while((r=r[n]));}else{do{if(r.nodeType!=1){continue; +}this[c][this.getUID(r)]=t++;}while((r=r[n]));}}q=q||"n";var v=this.cacheNTH[q]||this.parseNTHArgument(q);if(!v){return false;}var y=v.a,x=v.b,w=this[c][u]; +if(y==0){return x==w;}if(y>0){if(w<x){return false;}}else{if(x<w){return false;}}return((w-x)%y)==0;};};k.pushArray=function(p,c,r,o,n,q){if(this.matchSelector(p,c,r,o,n,q)){this.found.push(p); +}};k.pushUID=function(q,c,s,p,n,r){var o=this.getUID(q);if(!this.uniques[o]&&this.matchSelector(q,c,s,p,n,r)){this.uniques[o]=true;this.found.push(q);}}; +k.matchNode=function(n,o){if(this.isHTMLDocument&&this.nativeMatchesSelector){try{return this.nativeMatchesSelector.call(n,o.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g,'[$1="$2"]')); +}catch(u){}}var t=this.Slick.parse(o);if(!t){return true;}var r=t.expressions,s=0,q;for(q=0;(currentExpression=r[q]);q++){if(currentExpression.length==1){var p=currentExpression[0]; +if(this.matchSelector(n,(this.isXMLDocument)?p.tag:p.tag.toUpperCase(),p.id,p.classes,p.attributes,p.pseudos)){return true;}s++;}}if(s==t.length){return false; +}var c=this.search(this.document,t),v;for(q=0;v=c[q++];){if(v===n){return true;}}return false;};k.matchPseudo=function(q,c,p){var n="pseudo:"+c;if(this[n]){return this[n](q,p); +}var o=this.getAttribute(q,c);return(p)?p==o:!!o;};k.matchSelector=function(o,v,c,p,q,s){if(v){var t=(this.isXMLDocument)?o.nodeName:o.nodeName.toUpperCase(); +if(v=="*"){if(t<"@"){return false;}}else{if(t!=v){return false;}}}if(c&&o.getAttribute("id")!=c){return false;}var r,n,u;if(p){for(r=p.length;r--;){u=this.getAttribute(o,"class"); +if(!(u&&p[r].regexp.test(u))){return false;}}}if(q){for(r=q.length;r--;){n=q[r];if(n.operator?!n.test(this.getAttribute(o,n.key)):!this.hasAttribute(o,n.key)){return false; +}}}if(s){for(r=s.length;r--;){n=s[r];if(!this.matchPseudo(o,n.key,n.value)){return false;}}}return true;};var j={" ":function(q,w,n,r,s,u,p){var t,v,o; +if(this.isHTMLDocument){getById:if(n){v=this.document.getElementById(n);if((!v&&q.all)||(this.idGetsName&&v&&v.getAttributeNode("id").nodeValue!=n)){o=q.all[n]; +if(!o){return;}if(!o[0]){o=[o];}for(t=0;v=o[t++];){var c=v.getAttributeNode("id");if(c&&c.nodeValue==n){this.push(v,w,null,r,s,u);break;}}return;}if(!v){if(this.contains(this.root,q)){return; +}else{break getById;}}else{if(this.document!==q&&!this.contains(q,v)){return;}}this.push(v,w,null,r,s,u);return;}getByClass:if(r&&q.getElementsByClassName&&!this.brokenGEBCN){o=q.getElementsByClassName(p.join(" ")); +if(!(o&&o.length)){break getByClass;}for(t=0;v=o[t++];){this.push(v,w,n,null,s,u);}return;}}getByTag:{o=q.getElementsByTagName(w);if(!(o&&o.length)){break getByTag; +}if(!this.brokenStarGEBTN){w=null;}for(t=0;v=o[t++];){this.push(v,w,n,r,s,u);}}},">":function(p,c,r,o,n,q){if((p=p.firstChild)){do{if(p.nodeType==1){this.push(p,c,r,o,n,q); +}}while((p=p.nextSibling));}},"+":function(p,c,r,o,n,q){while((p=p.nextSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);break;}}},"^":function(p,c,r,o,n,q){p=p.firstChild; +if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:+"](p,c,r,o,n,q);}}},"~":function(q,c,s,p,n,r){while((q=q.nextSibling)){if(q.nodeType!=1){continue; +}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}},"++":function(p,c,r,o,n,q){this["combinator:+"](p,c,r,o,n,q); +this["combinator:!+"](p,c,r,o,n,q);},"~~":function(p,c,r,o,n,q){this["combinator:~"](p,c,r,o,n,q);this["combinator:!~"](p,c,r,o,n,q);},"!":function(p,c,r,o,n,q){while((p=p.parentNode)){if(p!==this.document){this.push(p,c,r,o,n,q); +}}},"!>":function(p,c,r,o,n,q){p=p.parentNode;if(p!==this.document){this.push(p,c,r,o,n,q);}},"!+":function(p,c,r,o,n,q){while((p=p.previousSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q); +break;}}},"!^":function(p,c,r,o,n,q){p=p.lastChild;if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:!+"](p,c,r,o,n,q);}}},"!~":function(q,c,s,p,n,r){while((q=q.previousSibling)){if(q.nodeType!=1){continue; +}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}}};for(var i in j){k["combinator:"+i]=j[i];}var l={empty:function(c){var n=c.firstChild; +return !(n&&n.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,n){return !this.matchNode(c,n);},contains:function(c,n){return(c.innerText||c.textContent||"").indexOf(n)>-1; +},"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false; +}}return true;},"only-child":function(o){var n=o;while((n=n.previousSibling)){if(n.nodeType==1){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeType==1){return false; +}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+(c+1)); +},even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var n=c.nodeName; +while((c=c.previousSibling)){if(c.nodeName==n){return false;}}return true;},"last-of-type":function(c){var n=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==n){return false; +}}return true;},"only-of-type":function(o){var n=o,p=o.nodeName;while((n=n.previousSibling)){if(n.nodeName==p){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeName==p){return false; +}}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex")); +},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for"); +},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href");},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style"); +},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null;},type:function(){return this.getAttribute("type"); +},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null;}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{}); +e.version="1.1.7";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true);};e.contains=function(c,n){k.setDocument(c); +return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n);return k.hasAttribute(n,c); +};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n; +return this;};e.lookupAttributeGetter=function(c){return k.attributeGetters[c];};e.definePseudo=function(c,n){k["pseudo:"+c]=function(p,o){return n.call(p,o); +};return this;};e.lookupPseudo=function(c){var n=k["pseudo:"+c];if(n){return function(o){return n.call(this,o);};}return null;};e.override=function(n,c){k.override(n,c); +return this;};e.isXML=k.isXML;e.uidOf=function(c){return k.getUIDHTML(c);};if(!this.Slick){this.Slick=e;}}).apply((typeof exports!="undefined")?exports:this); +var Element=this.Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={}; +}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0];b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length; +f<c;f++){a=d[f];if(g[a.key]!=null){continue;}if(a.value!=null&&a.operator=="="){g[a.key]=a.value;}else{if(!a.value&&!a.operator){g[a.key]=true;}}}}if(e.classList&&g["class"]==null){g["class"]=e.classList.join(" "); +}}return document.newElement(b,g);};if(Browser.Element){Element.prototype=Browser.Element.prototype;Element.prototype._fireEvent=(function(a){return function(b,c){return a.call(this,b,c); +};})(Element.prototype.fireEvent);}new Type("Element",Element).mirror(function(a){if(Array.prototype[a]){return;}var b={};b[a]=function(){var h=[],e=arguments,j=true; +for(var g=0,d=this.length;g<d;g++){var f=this[g],c=h[g]=f[a].apply(f,e);j=(j&&typeOf(c)=="element");}return(j)?new Elements(h):h;};Elements.implement(b); +});if(!Browser.Element){Element.parent=Object;Element.Prototype={"$constructor":Element,"$family":Function.from("element").hide()};Element.mirror(function(a,b){Element.Prototype[a]=b; +});}Element.Constructors={};var IFrame=new Type("IFrame",function(){var e=Array.link(arguments,{properties:Type.isObject,iframe:function(f){return(f!=null); +}});var c=e.properties||{},b;if(e.iframe){b=document.id(e.iframe);}var d=c.onload||function(){};delete c.onload;c.id=c.name=[c.id,c.name,b?(b.id||b.name):"IFrame_"+String.uniqueID()].pick(); +b=new Element(b||"iframe",c);var a=function(){d.call(b.contentWindow);};if(window.frames[c.id]){a();}else{b.addListener("load",a);}return b;});var Elements=this.Elements=function(a){if(a&&a.length){var e={},d; +for(var c=0;d=a[c++];){var b=Slick.uidOf(d);if(!e[b]){e[b]=true;this.push(d);}}}};Elements.prototype={length:0};Elements.parent=Array;new Type("Elements",Elements).implement({filter:function(a,b){if(!a){return this; +}return new Elements(Array.filter(this,(typeOf(a)=="string")?function(c){return c.match(a);}:a,b));}.protect(),push:function(){var d=this.length;for(var b=0,a=arguments.length; +b<a;b++){var c=document.id(arguments[b]);if(c){this[d++]=c;}}return(this.length=d);}.protect(),unshift:function(){var b=[];for(var c=0,a=arguments.length; +c<a;c++){var d=document.id(arguments[c]);if(d){b.push(d);}}return Array.prototype.unshift.apply(this,b);}.protect(),concat:function(){var b=new Elements(this); +for(var c=0,a=arguments.length;c<a;c++){var d=arguments[c];if(Type.isEnumerable(d)){b.append(d);}else{b.push(d);}}return b;}.protect(),append:function(c){for(var b=0,a=c.length; +b<a;b++){this.push(c[b]);}return this;}.protect(),empty:function(){while(this.length){delete this[--this.length];}return this;}.protect()});(function(){var f=Array.prototype.splice,a={"0":0,"1":1,length:2}; +f.call(a,1,1);if(a[1]==1){Elements.implement("splice",function(){var g=this.length;var e=f.apply(this,arguments);while(g>=this.length){delete this[g--]; +}return e;}.protect());}Array.forEachMethod(function(g,e){Elements.implement(e,g);});Array.mirror(Elements);var d;try{d=(document.createElement("<input name=x>").name=="x"); +}catch(b){}var c=function(e){return(""+e).replace(/&/g,"&").replace(/"/g,""");};Document.implement({newElement:function(e,g){if(g&&g.checked!=null){g.defaultChecked=g.checked; +}if(d&&g){e="<"+e;if(g.name){e+=' name="'+c(g.name)+'"';}if(g.type){e+=' type="'+c(g.type)+'"';}e+=">";delete g.name;delete g.type;}return this.id(this.createElement(e)).set(g); +}});})();(function(){Slick.uidOf(window);Slick.uidOf(document);Document.implement({newTextNode:function(e){return this.createTextNode(e);},getDocument:function(){return this; +},getWindow:function(){return this.window;},id:(function(){var e={string:function(L,K,l){L=Slick.find(l,"#"+L.replace(/(\W)/g,"\\$1"));return(L)?e.element(L,K):null; +},element:function(K,L){Slick.uidOf(K);if(!L&&!K.$family&&!(/^(?:object|embed)$/i).test(K.tagName)){var l=K.fireEvent;K._fireEvent=function(M,N){return l(M,N); +};Object.append(K,Element.Prototype);}return K;},object:function(K,L,l){if(K.toElement){return e.element(K.toElement(l),L);}return null;}};e.textnode=e.whitespace=e.window=e.document=function(l){return l; +};return function(K,M,L){if(K&&K.$family&&K.uniqueNumber){return K;}var l=typeOf(K);return(e[l])?e[l](K,M,L||document):null;};})()});if(window.$==null){Window.implement("$",function(e,l){return document.id(e,l,this.document); +});}Window.implement({getDocument:function(){return this.document;},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(e){return Slick.search(this,e,new Elements); +},getElement:function(e){return document.id(Slick.find(this,e));}});var p={contains:function(e){return Slick.contains(this,e);}};if(!document.contains){Document.implement(p); +}if(!document.createElement("div").contains){Element.implement(p);}var v=function(L,K){if(!L){return K;}L=Object.clone(Slick.parse(L));var l=L.expressions; +for(var e=l.length;e--;){l[e][0].combinator=K;}return L;};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(e,l){Element.implement(l,function(K){return this.getElement(v(K,e)); +});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(e,l){Element.implement(l,function(K){return this.getElements(v(K,e)); +});});Element.implement({getFirst:function(e){return document.id(Slick.search(this,v(e,">"))[0]);},getLast:function(e){return document.id(Slick.search(this,v(e,">")).getLast()); +},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(e){return document.id(Slick.find(this,"#"+(""+e).replace(/(\W)/g,"\\$1"))); +},match:function(e){return !e||Slick.match(this,e);}});if(window.$$==null){Window.implement("$$",function(e){if(arguments.length==1){if(typeof e=="string"){return Slick.search(this.document,e,new Elements); +}else{if(Type.isEnumerable(e)){return new Elements(e);}}}return new Elements(arguments);});}var A={before:function(l,e){var K=e.parentNode;if(K){K.insertBefore(l,e); +}},after:function(l,e){var K=e.parentNode;if(K){K.insertBefore(l,e.nextSibling);}},bottom:function(l,e){e.appendChild(l);},top:function(l,e){e.insertBefore(l,e.firstChild); +}};A.inside=A.bottom;var n={},d={};var o={};Array.forEach(["type","value","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","rowSpan","tabIndex","useMap"],function(e){o[e.toLowerCase()]=e; +});o.html="innerHTML";o.text=(document.createElement("div").textContent==null)?"innerText":"textContent";Object.forEach(o,function(l,e){d[e]=function(K,L){K[l]=L; +};n[e]=function(K){return K[l];};});var B=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked","autofocus","controls","autoplay","loop"]; +var k={};Array.forEach(B,function(e){var l=e.toLowerCase();k[l]=e;d[l]=function(K,L){K[e]=!!L;};n[l]=function(K){return !!K[e];};});Object.append(d,{"class":function(e,l){("className" in e)?e.className=(l||""):e.setAttribute("class",l); +},"for":function(e,l){("htmlFor" in e)?e.htmlFor=l:e.setAttribute("for",l);},style:function(e,l){(e.style)?e.style.cssText=l:e.setAttribute("style",l); +},value:function(e,l){e.value=(l!=null)?l:"";}});n["class"]=function(e){return("className" in e)?e.className||null:e.getAttribute("class");};var f=document.createElement("button"); +try{f.type="button";}catch(E){}if(f.type!="button"){d.type=function(e,l){e.setAttribute("type",l);};}f=null;var s=document.createElement("input");s.value="t"; +s.type="submit";if(s.value!="t"){d.type=function(l,e){var K=l.value;l.type=e;l.value=K;};}s=null;var u=(function(e){e.random="attribute";return(e.getAttribute("random")=="attribute"); +})(document.createElement("div"));var i=(function(e){e.innerHTML='<object><param name="should_fix" value="the unknown"></object>';return e.cloneNode(true).firstChild.childNodes.length!=1; +})(document.createElement("div"));var j=!!document.createElement("div").classList;var F=function(e){var l=(e||"").clean().split(" "),K={};return l.filter(function(L){if(L!==""&&!K[L]){return K[L]=L; +}});};var t=function(e){this.classList.add(e);};var g=function(e){this.classList.remove(e);};Element.implement({setProperty:function(l,K){var L=d[l.toLowerCase()]; +if(L){L(this,K);}else{var e;if(u){e=this.retrieve("$attributeWhiteList",{});}if(K==null){this.removeAttribute(l);if(u){delete e[l];}}else{this.setAttribute(l,""+K); +if(u){e[l]=true;}}}return this;},setProperties:function(e){for(var l in e){this.setProperty(l,e[l]);}return this;},getProperty:function(M){var K=n[M.toLowerCase()]; +if(K){return K(this);}if(u){var l=this.getAttributeNode(M),L=this.retrieve("$attributeWhiteList",{});if(!l){return null;}if(l.expando&&!L[M]){var N=this.outerHTML; +if(N.substr(0,N.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(M)<0){return null;}L[M]=true;}}var e=Slick.getAttribute(this,M);return(!e&&!Slick.hasAttribute(this,M))?null:e; +},getProperties:function(){var e=Array.from(arguments);return e.map(this.getProperty,this).associate(e);},removeProperty:function(e){return this.setProperty(e,null); +},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;},set:function(K,l){var e=Element.Properties[K];(e&&e.set)?e.set.call(this,l):this.setProperty(K,l); +}.overloadSetter(),get:function(l){var e=Element.Properties[l];return(e&&e.get)?e.get.apply(this):this.getProperty(l);}.overloadGetter(),erase:function(l){var e=Element.Properties[l]; +(e&&e.erase)?e.erase.apply(this):this.removeProperty(l);return this;},hasClass:j?function(e){return this.classList.contains(e);}:function(e){return this.className.clean().contains(e," "); +},addClass:j?function(e){F(e).forEach(t,this);return this;}:function(e){this.className=F(e+" "+this.className).join(" ");return this;},removeClass:j?function(e){F(e).forEach(g,this); +return this;}:function(e){var l=F(this.className);F(e).forEach(l.erase,l);this.className=l.join(" ");return this;},toggleClass:function(e,l){if(l==null){l=!this.hasClass(e); +}return(l)?this.addClass(e):this.removeClass(e);},adopt:function(){var L=this,e,N=Array.flatten(arguments),M=N.length;if(M>1){L=e=document.createDocumentFragment(); +}for(var K=0;K<M;K++){var l=document.id(N[K],true);if(l){L.appendChild(l);}}if(e){this.appendChild(e);}return this;},appendText:function(l,e){return this.grab(this.getDocument().newTextNode(l),e); +},grab:function(l,e){A[e||"bottom"](document.id(l,true),this);return this;},inject:function(l,e){A[e||"bottom"](this,document.id(l,true));return this;},replaces:function(e){e=document.id(e,true); +e.parentNode.replaceChild(this,e);return this;},wraps:function(l,e){l=document.id(l,true);return this.replaces(l).grab(l,e);},getSelected:function(){this.selectedIndex; +return new Elements(Array.from(this.options).filter(function(e){return e.selected;}));},toQueryString:function(){var e=[];this.getElements("input, select, textarea").each(function(K){var l=K.type; +if(!K.name||K.disabled||l=="submit"||l=="reset"||l=="file"||l=="image"){return;}var L=(K.get("tag")=="select")?K.getSelected().map(function(M){return document.id(M).get("value"); +}):((l=="radio"||l=="checkbox")&&!K.checked)?null:K.get("value");Array.from(L).each(function(M){if(typeof M!="undefined"){e.push(encodeURIComponent(K.name)+"="+encodeURIComponent(M)); +}});});return e.join("&");}});var I={before:"beforeBegin",after:"afterEnd",bottom:"beforeEnd",top:"afterBegin",inside:"beforeEnd"};Element.implement("appendHTML",("insertAdjacentHTML" in document.createElement("div"))?function(l,e){this.insertAdjacentHTML(I[e||"bottom"],l); +return this;}:function(P,M){var K=new Element("div",{html:P}),O=K.childNodes,L=K.firstChild;if(!L){return this;}if(O.length>1){L=document.createDocumentFragment(); +for(var N=0,e=O.length;N<e;N++){L.appendChild(O[N]);}}A[M||"bottom"](L,this);return this;});var m={},D={};var G=function(e){return(D[e]||(D[e]={}));};var z=function(l){var e=l.uniqueNumber; +if(l.removeEvents){l.removeEvents();}if(l.clearAttributes){l.clearAttributes();}if(e!=null){delete m[e];delete D[e];}return l;};var H={input:"checked",option:"selected",textarea:"value"}; +Element.implement({destroy:function(){var e=z(this).getElementsByTagName("*");Array.each(e,z);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose); +return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},clone:function(N,L){N=N!==false;var S=this.cloneNode(N),K=[S],M=[this],Q; +if(N){K.append(Array.from(S.getElementsByTagName("*")));M.append(Array.from(this.getElementsByTagName("*")));}for(Q=K.length;Q--;){var O=K[Q],R=M[Q];if(!L){O.removeAttribute("id"); +}if(O.clearAttributes){O.clearAttributes();O.mergeAttributes(R);O.removeAttribute("uniqueNumber");if(O.options){var V=O.options,e=R.options;for(var P=V.length; +P--;){V[P].selected=e[P].selected;}}}var l=H[R.tagName.toLowerCase()];if(l&&R[l]){O[l]=R[l];}}if(i){var T=S.getElementsByTagName("object"),U=this.getElementsByTagName("object"); +for(Q=T.length;Q--;){T[Q].outerHTML=U[Q].outerHTML;}}return document.id(S);}});[Element,Window,Document].invoke("implement",{addListener:function(l,e){if(window.attachEvent&&!window.addEventListener){m[Slick.uidOf(this)]=this; +}if(this.addEventListener){this.addEventListener(l,e,!!arguments[2]);}else{this.attachEvent("on"+l,e);}return this;},removeListener:function(l,e){if(this.removeEventListener){this.removeEventListener(l,e,!!arguments[2]); +}else{this.detachEvent("on"+l,e);}return this;},retrieve:function(l,e){var L=G(Slick.uidOf(this)),K=L[l];if(e!=null&&K==null){K=L[l]=e;}return K!=null?K:null; +},store:function(l,e){var K=G(Slick.uidOf(this));K[l]=e;return this;},eliminate:function(e){var l=G(Slick.uidOf(this));delete l[e];return this;}});if(window.attachEvent&&!window.addEventListener){var J=function(){Object.each(m,z); +if(window.CollectGarbage){CollectGarbage();}window.removeListener("unload",J);};window.addListener("unload",J);}Element.Properties={};Element.Properties.style={set:function(e){this.style.cssText=e; +},get:function(){return this.style.cssText;},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase(); +}};Element.Properties.html={set:function(e){if(e==null){e="";}else{if(typeOf(e)=="array"){e=e.join("");}}this.innerHTML=e;},erase:function(){this.innerHTML=""; +}};var a=true,h=true,C=true;var x=document.createElement("div");x.innerHTML="<nav></nav>";a=(x.childNodes.length==1);if(!a){var w="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),b=document.createDocumentFragment(),y=w.length; +while(y--){b.createElement(w[y]);}}x=null;h=Function.attempt(function(){var e=document.createElement("table");e.innerHTML="<tr><td></td></tr>";return true; +});var c=document.createElement("tr"),r="<td></td>";c.innerHTML=r;C=(c.innerHTML==r);c=null;if(!h||!C||!a){Element.Properties.html.set=(function(l){var e={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]}; +e.thead=e.tfoot=e.tbody;return function(K){var L=e[this.get("tag")];if(!L&&!a){L=[0,"",""];}if(!L){return l.call(this,K);}var O=L[0],N=document.createElement("div"),M=N; +if(!a){b.appendChild(N);}N.innerHTML=[L[1],K,L[2]].flatten().join("");while(O--){M=M.firstChild;}this.empty().adopt(M.childNodes);if(!a){b.removeChild(N); +}N=null;};})(Element.Properties.html.set);}var q=document.createElement("form");q.innerHTML="<select><option>s</option></select>";if(q.firstChild.value!="s"){Element.Properties.value={set:function(N){var l=this.get("tag"); +if(l!="select"){return this.setProperty("value",N);}var K=this.getElements("option");N=String(N);for(var L=0;L<K.length;L++){var M=K[L],e=M.getAttributeNode("value"),O=(e&&e.specified)?M.value:M.get("text"); +if(O===N){return M.selected=true;}}},get:function(){var K=this,l=K.get("tag");if(l!="select"&&l!="option"){return this.getProperty("value");}if(l=="select"&&!(K=K.getSelected()[0])){return""; +}var e=K.getAttributeNode("value");return(e&&e.specified)?K.value:K.get("text");}};}q=null;if(document.createElement("div").getAttributeNode("id")){Element.Properties.id={set:function(e){this.id=this.getAttributeNode("id").value=e; +},get:function(){return this.id||null;},erase:function(){this.id=this.getAttributeNode("id").value="";}};}})();(function(){var l=document.html,f;f=document.createElement("div"); +f.style.color="red";f.style.color=null;var e=f.style.color=="red";var k="1px solid #123abc";f.style.border=k;var o=f.style.border!=k;f=null;var n=!!window.getComputedStyle; +Element.Properties.styles={set:function(r){this.setStyles(r);}};var j=(l.style.opacity!=null),g=(l.style.filter!=null),q=/alpha\(opacity=([\d.]+)\)/i;var b=function(s,r){s.store("$opacity",r); +s.style.visibility=r>0||r==null?"visible":"hidden";};var p=function(r,v,u){var t=r.style,s=t.filter||r.getComputedStyle("filter")||"";t.filter=(v.test(s)?s.replace(v,u):s+" "+u).trim(); +if(!t.filter){t.removeAttribute("filter");}};var h=(j?function(s,r){s.style.opacity=r;}:(g?function(s,r){if(!s.currentStyle||!s.currentStyle.hasLayout){s.style.zoom=1; +}if(r==null||r==1){p(s,q,"");if(r==1&&i(s)!=1){p(s,q,"alpha(opacity=100)");}}else{p(s,q,"alpha(opacity="+(r*100).limit(0,100).round()+")");}}:b));var i=(j?function(s){var r=s.style.opacity||s.getComputedStyle("opacity"); +return(r=="")?1:r.toFloat();}:(g?function(s){var t=(s.style.filter||s.getComputedStyle("filter")),r;if(t){r=t.match(q);}return(r==null||t==null)?1:(r[1]/100); +}:function(s){var r=s.retrieve("$opacity");if(r==null){r=(s.style.visibility=="hidden"?0:1);}return r;}));var d=(l.style.cssFloat==null)?"styleFloat":"cssFloat",a={left:"0%",top:"0%",center:"50%",right:"100%",bottom:"100%"},c=(l.style.backgroundPositionX!=null); +var m=function(r,s){if(s=="backgroundPosition"){r.removeAttribute(s+"X");s+="Y";}r.removeAttribute(s);};Element.implement({getComputedStyle:function(t){if(!n&&this.currentStyle){return this.currentStyle[t.camelCase()]; +}var s=Element.getDocument(this).defaultView,r=s?s.getComputedStyle(this,null):null;return(r)?r.getPropertyValue((t==d)?"float":t.hyphenate()):"";},setStyle:function(s,r){if(s=="opacity"){if(r!=null){r=parseFloat(r); +}h(this,r);return this;}s=(s=="float"?d:s).camelCase();if(typeOf(r)!="string"){var t=(Element.Styles[s]||"@").split(" ");r=Array.from(r).map(function(v,u){if(!t[u]){return""; +}return(typeOf(v)=="number")?t[u].replace("@",Math.round(v)):v;}).join(" ");}else{if(r==String(Number(r))){r=Math.round(r);}}this.style[s]=r;if((r==""||r==null)&&e&&this.style.removeAttribute){m(this.style,s); +}return this;},getStyle:function(x){if(x=="opacity"){return i(this);}x=(x=="float"?d:x).camelCase();var r=this.style[x];if(!r||x=="zIndex"){if(Element.ShortStyles.hasOwnProperty(x)){r=[]; +for(var w in Element.ShortStyles[x]){r.push(this.getStyle(w));}return r.join(" ");}r=this.getComputedStyle(x);}if(c&&/^backgroundPosition[XY]?$/.test(x)){return r.replace(/(top|right|bottom|left)/g,function(s){return a[s]; +})||"0px";}if(!r&&x=="backgroundPosition"){return"0px 0px";}if(r){r=String(r);var u=r.match(/rgba?\([\d\s,]+\)/);if(u){r=r.replace(u[0],u[0].rgbToHex()); +}}if(!n&&!this.style[x]){if((/^(height|width)$/).test(x)&&!(/px$/.test(r))){var t=(x=="width")?["left","right"]:["top","bottom"],v=0;t.each(function(s){v+=this.getStyle("border-"+s+"-width").toInt()+this.getStyle("padding-"+s).toInt(); +},this);return this["offset"+x.capitalize()]-v+"px";}if((/^border(.+)Width|margin|padding/).test(x)&&isNaN(parseFloat(r))){return"0px";}}if(o&&/^border(Top|Right|Bottom|Left)?$/.test(x)&&/^#/.test(r)){return r.replace(/^(.+)\s(.+)\s(.+)$/,"$2 $3 $1"); +}return r;},setStyles:function(s){for(var r in s){this.setStyle(r,s[r]);}return this;},getStyles:function(){var r={};Array.flatten(arguments).each(function(s){r[s]=this.getStyle(s); +},this);return r;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundSize:"@px",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"}; +Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(x){var w=Element.ShortStyles; +var s=Element.Styles;["margin","padding"].each(function(y){var z=y+x;w[y][z]=s[z]="@px";});var v="border"+x;w.border[v]=s[v]="@px @ rgb(@, @, @)";var u=v+"Width",r=v+"Style",t=v+"Color"; +w[v]={};w.borderWidth[u]=w[v][u]=s[u]="@px";w.borderStyle[r]=w[v][r]=s[r]="@";w.borderColor[t]=w[v][t]=s[t]="rgb(@, @, @)";});if(c){Element.ShortStyles.backgroundPosition={backgroundPositionX:"@",backgroundPositionY:"@"}; +}})();(function(){Element.Properties.events={set:function(b){this.addEvents(b);}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{}); +if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this;}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f); +}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k);}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j); +};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow());if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]); +}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events");if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d); +if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e];if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e); +}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this; +},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);}return this;}var c=this.retrieve("events");if(!c){return this; +}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);},this);delete c[b]; +}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c); +}else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b); +}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,hashchange:1,popstate:2,error:1,abort:1,scroll:1}; +Element.Events={mousewheel:{base:"onwheel" in document?"wheel":"onmousewheel" in document?"mousewheel":"DOMMouseScroll"}};var a=function(b){var c=b.relatedTarget; +if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c));};if("onmouseenter" in document.documentElement){Element.NativeEvents.mouseenter=Element.NativeEvents.mouseleave=2; +Element.MouseenterCheck=a;}else{Element.Events.mouseenter={base:"mouseover",condition:a};Element.Events.mouseleave={base:"mouseout",condition:a};}if(!window.addEventListener){Element.NativeEvents.propertychange=2; +Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change";},condition:function(b){return b.type!="propertychange"||b.event.propertyName=="checked"; +}};}})();(function(){var c=!!window.addEventListener;Element.NativeEvents.focusin=Element.NativeEvents.focusout=2;var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p); +}p=document.id(p.parentNode);}};var a={mouseenter:{base:"mouseover",condition:Element.MouseenterCheck},mouseleave:{base:"mouseout",condition:Element.MouseenterCheck},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}}; +var b="$delegation:";var i=function(l){return{base:"focusin",remove:function(m,o){var p=m.retrieve(b+l+"listeners",{})[o];if(p&&p.forms){for(var n=p.forms.length; +n--;){p.forms[n].removeEvent(l,p.fns[n]);}}},listen:function(x,r,v,n,t,s){var o=(t.get("tag")=="form")?t:n.target.getParent("form");if(!o){return;}var u=x.retrieve(b+l+"listeners",{}),p=u[s]||{forms:[],fns:[]},m=p.forms,w=p.fns; +if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEvent(l,q);w.push(q);u[s]=p;x.store(b+l+"listeners",u);}};};var d=function(l){return{base:"focusin",listen:function(m,n,p,q,r){var o={blur:function(){this.removeEvents(o); +}};o[l]=function(s){k(m,n,p,s,r);};q.target.addEvents(o);}};};if(!c){Object.append(a,{submit:i("submit"),reset:i("reset"),change:d("change"),select:d("select")}); +}var h=Element.prototype,f=h.addEvent,j=h.removeEvent;var e=function(l,m){return function(r,q,n){if(r.indexOf(":relay")==-1){return l.call(this,r,q,n); +}var o=Slick.parse(r).expressions[0][0];if(o.pseudos[0].key!="relay"){return l.call(this,r,q,n);}var p=o.tag;o.pseudos.slice(1).each(function(s){p+=":"+s.key+(s.value?"("+s.value+")":""); +});l.call(this,r,q);return m.call(this,p,o.pseudos[0].value,q);};};var g={addEvent:function(v,q,x){var t=this.retrieve("$delegates",{}),r=t[v];if(r){for(var y in r){if(r[y].fn==x&&r[y].match==q){return this; +}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(n.condition||w&&w.condition){var l=q,m=n.condition||w.condition; +q=function(C,B){return l(C,B)&&m.call(C,B,v);};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s); +}}:function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture); +},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r];if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u); +}delete p[u];q[m]=p;return j.call(this,r,w,l.capture);}var o,v;if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o); +}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o);}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)}); +})();(function(){var h=document.createElement("div"),e=document.createElement("div");h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null; +var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName);};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n); +}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize();}return{x:this.offsetWidth,y:this.offsetHeight}; +},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};},getScroll:function(){if(a(this)){return this.getWindow().getScroll(); +}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0};while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop; +n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}var n=(k(m,"position")=="static")?i:l; +while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}try{return m.offsetParent; +}catch(n){}return null;},getOffsets:function(){var n=this.getBoundingClientRect;if(n){var r=this.getBoundingClientRect(),p=document.id(this.getDocument().documentElement),q=p.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed"); +return{x:r.left.toInt()+t.x+((s)?0:q.x)-p.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-p.clientTop};}var o=this,m={x:0,y:0};if(a(this)){return m;}while(o&&!a(o)){m.x+=o.offsetLeft; +m.y+=o.offsetTop;o=o.offsetParent;}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls();var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition(); +return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates();}var m=this.getPosition(o),n=this.getSize(); +var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")}; +},setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight}; +},getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body; +return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize(); +return{top:0,left:0,bottom:m.y,right:m.x,height:m.y,width:m.x};}});var k=Element.getComputedStyle;function j(m,n){return k(m,n).toInt()||0;}function c(m){return k(m,"-moz-box-sizing")=="border-box"; +}function g(m){return j(m,"border-top-width");}function b(m){return j(m,"border-left-width");}function a(m){return(/^(?:body|html)$/i).test(m.tagName); +}function f(m){var n=m.getDocument();return(!n.compatMode||n.compatMode=="CSS1Compat")?n.html:n.body;}})();Element.alias({position:"setPosition"});[Window,Document,Element].invoke("implement",{getHeight:function(){return this.getSize().y; +},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x; +},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y; +},getLeft:function(){return this.getPosition().x;}});(function(){var f=this.Fx=new Class({Implements:[Chain,Events,Options],options:{fps:60,unit:false,duration:500,frames:null,frameSkip:true,link:"ignore"},initialize:function(g){this.subject=this.subject||this; +this.setOptions(g);},getTransition:function(){return function(g){return -(Math.cos(Math.PI*g)-1)/2;};},step:function(g){if(this.options.frameSkip){var h=(this.time!=null)?(g-this.time):0,i=h/this.frameInterval; +this.time=g;this.frame+=i;}else{this.frame++;}if(this.frame<this.frames){var j=this.transition(this.frame/this.frames);this.set(this.compute(this.from,this.to,j)); +}else{this.frame=this.frames;this.set(this.compute(this.from,this.to,1));this.stop();}},set:function(g){return g;},compute:function(i,h,g){return f.compute(i,h,g); +},check:function(){if(!this.isRunning()){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this)); +return false;}return false;},start:function(k,j){if(!this.check(k,j)){return this;}this.from=k;this.to=j;this.frame=(this.options.frameSkip)?0:-1;this.time=null; +this.transition=this.getTransition();var i=this.options.frames,h=this.options.fps,g=this.options.duration;this.duration=f.Durations[g]||g.toInt();this.frameInterval=1000/h; +this.frames=i||Math.round(this.duration/this.frameInterval);this.fireEvent("start",this.subject);b.call(this,h);return this;},stop:function(){if(this.isRunning()){this.time=null; +d.call(this,this.options.fps);if(this.frames==this.frame){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject); +}}else{this.fireEvent("stop",this.subject);}}return this;},cancel:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);this.frame=this.frames; +this.fireEvent("cancel",this.subject).clearChain();}return this;},pause:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);}return this; +},resume:function(){if(this.isPaused()){b.call(this,this.options.fps);}return this;},isRunning:function(){var g=e[this.options.fps];return g&&g.contains(this); +},isPaused:function(){return(this.frame<this.frames)&&!this.isRunning();}});f.compute=function(i,h,g){return(h-i)*g+i;};f.Durations={"short":250,normal:500,"long":1000}; +var e={},c={};var a=function(){var h=Date.now();for(var j=this.length;j--;){var g=this[j];if(g){g.step(h);}}};var b=function(h){var g=e[h]||(e[h]=[]);g.push(this); +if(!c[h]){c[h]=a.periodical(Math.round(1000/h),g);}};var d=function(h){var g=e[h];if(g){g.erase(this);if(!g.length&&c[h]){delete e[h];c[h]=clearInterval(c[h]); +}}};})();Fx.CSS=new Class({Extends:Fx,prepare:function(b,e,a){a=Array.from(a);var h=a[0],g=a[1];if(g==null){g=h;h=b.getStyle(e);var c=this.options.unit; +if(c&&h&&typeof h=="string"&&h.slice(-c.length)!=c&&parseFloat(h)!=0){b.setStyle(e,g+c);var d=b.getComputedStyle(e);if(!(/px$/.test(d))){d=b.style[("pixel-"+e).camelCase()]; +if(d==null){var f=b.style.left;b.style.left=g+c;d=b.style.pixelLeft;b.style.left=f;}}h=(g||1)/(parseFloat(d)||1)*(parseFloat(h)||0);b.setStyle(e,h+c);}}return{from:this.parse(h),to:this.parse(g)}; +},parse:function(a){a=Function.from(a)();a=(typeof a=="string")?a.split(" "):Array.from(a);return a.map(function(c){c=String(c);var b=false;Object.each(Fx.CSS.Parsers,function(f,e){if(b){return; +}var d=f.parse(c);if(d||d===0){b={value:d,parser:f};}});b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser}); +});a.$family=Function.from("fx:css:value");return a;},serve:function(c,b){if(typeOf(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b)); +});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var d={},c=new RegExp("^"+a.escapeRegExp()+"$"); +var b=function(e){Array.each(e,function(h,f){if(h.media){b(h.rules||h.cssRules);return;}if(!h.style){return;}var g=(h.selectorText)?h.selectorText.replace(/^\w+/,function(i){return i.toLowerCase(); +}):null;if(!g||!c.test(g)){return;}Object.each(Element.Styles,function(j,i){if(!h.style[i]||Element.ShortStyles[i]){return;}j=String(h.style[i]);d[i]=((/^rgb/).test(j))?j.rgbToHex():j; +});});};Array.each(document.styleSheets,function(g,f){var e=g.href;if(e&&e.indexOf("://")>-1&&e.indexOf(document.domain)==-1){return;}var h=g.rules||g.cssRules; +b(h);});return Fx.CSS.Cache[a]=d;}});Fx.CSS.Cache={};Fx.CSS.Parsers={Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true); +}return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a)); +});},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:Function.from(false),compute:function(b,a){return a; +},serve:function(a){return a;}}};Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);},set:function(b,a){if(arguments.length==1){a=b; +b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this; +}var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);return this.parent(a.from,a.to); +}});Element.Properties.tween={set:function(a){this.get("tween").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("tween");if(!a){a=new Fx.Tween(this,{link:"cancel"}); +this.store("tween",a);}return a;}};Element.implement({tween:function(a,c,b){this.get("tween").start(a,c,b);return this;},fade:function(d){var e=this.get("tween"),g,c=["opacity"].append(arguments),a; +if(c[1]==null){c[1]="toggle";}switch(c[1]){case"in":g="start";c[1]=1;break;case"out":g="start";c[1]=0;break;case"show":g="set";c[1]=1;break;case"hide":g="set"; +c[1]=0;break;case"toggle":var b=this.retrieve("fade:flag",this.getStyle("opacity")==1);g="start";c[1]=b?0:1;this.store("fade:flag",!b);a=true;break;default:g="start"; +}if(!a){this.eliminate("fade:flag");}e[g].apply(e,c);var f=c[c.length-1];if(g=="set"||f!=0){this.setStyle("visibility",f==0?"hidden":"visible");}else{e.chain(function(){this.element.setStyle("visibility","hidden"); +this.callChain();});}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));a=(a=="transparent")?"#fff":a; +}var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original")); +b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a); +},set:function(a){if(typeof a=="string"){a=this.search(a);}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={}; +for(var b in e){a[b]=this.parent(e[b],d[b],c);}return a;},start:function(b){if(!this.check(b)){return this;}if(typeof b=="string"){b=this.search(b);}var e={},d={}; +for(var c in b){var a=this.prepare(this.element,c,b[c]);e[c]=a.from;d[c]=a.to;}return this.parent(e,d);}});Element.Properties.morph={set:function(a){this.get("morph").cancel().setOptions(a); +return this;},get:function(){var a=this.retrieve("morph");if(!a){a=new Fx.Morph(this,{link:"cancel"});this.store("morph",a);}return a;}};Element.implement({morph:function(a){this.get("morph").start(a); +return this;}});Fx.implement({getTransition:function(){var a=this.options.transition||Fx.Transitions.Sine.easeInOut;if(typeof a=="string"){var b=a.split(":"); +a=Fx.Transitions;a=a[b[0]]||a[b[0].capitalize()];if(b[1]){a=a["ease"+b[1].capitalize()+(b[2]?b[2].capitalize():"")];}}return a;}});Fx.Transition=function(c,b){b=Array.from(b); +var a=function(d){return c(d,b);};return Object.append(a,{easeIn:a,easeOut:function(d){return 1-c(1-d,b);},easeInOut:function(d){return(d<=0.5?c(2*d,b):(2-c(2*(1-d),b)))/2; +}});};Fx.Transitions={linear:function(a){return a;}};Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);}};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a&&a[0]||6); +},Expo:function(a){return Math.pow(2,8*(a-1));},Circ:function(a){return 1-Math.sin(Math.acos(a));},Sine:function(a){return 1-Math.cos(a*Math.PI/2);},Back:function(b,a){a=a&&a[0]||1.618; +return Math.pow(b,2)*((a+1)*b-a);},Bounce:function(f){var e;for(var d=0,c=1;1;d+=c,c/=2){if(f>=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);break;}}return e; +},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a&&a[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,a+2); +});});(function(){var d=function(){},a=("onprogress" in new Browser.Request);var c=this.Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,timeout:0,noCache:false},initialize:function(e){this.xhr=new Browser.Request(); +this.setOptions(e);this.headers=this.options.headers;},onStateChange:function(){var e=this.xhr;if(e.readyState!=4||!this.running){return;}this.running=false; +this.status=0;Function.attempt(function(){var f=e.status;this.status=(f==1223)?204:f;}.bind(this));e.onreadystatechange=d;if(a){e.onprogress=e.onloadstart=d; +}clearTimeout(this.timer);this.response={text:this.xhr.responseText||"",xml:this.xhr.responseXML};if(this.options.isSuccess.call(this,this.status)){this.success(this.response.text,this.response.xml); +}else{this.failure();}},isSuccess:function(){var e=this.status;return(e>=200&&e<300);},isRunning:function(){return !!this.running;},processScripts:function(e){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return Browser.exec(e); +}return e.stripScripts(this.options.evalScripts);},success:function(f,e){this.onSuccess(this.processScripts(f),e);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain(); +},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},loadstart:function(e){this.fireEvent("loadstart",[e,this.xhr]); +},progress:function(e){this.fireEvent("progress",[e,this.xhr]);},timeout:function(){this.fireEvent("timeout",this.xhr);},setHeader:function(e,f){this.headers[e]=f; +return this;},getHeader:function(e){return Function.attempt(function(){return this.xhr.getResponseHeader(e);}.bind(this));},check:function(){if(!this.running){return true; +}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));return false;}return false;},send:function(o){if(!this.check(o)){return this; +}this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.running=true;var l=typeOf(o);if(l=="string"||l=="element"){o={data:o};}var h=this.options; +o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString(); +break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e; +j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g; +}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.indexOf("?")>-1?"&":"?")+String.uniqueID(); +}if(j&&(e=="get"||e=="delete")){f+=(f.indexOf("?")>-1?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this); +}n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true; +}n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]); +}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}else{if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this); +}}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d; +if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e}; +if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e); +return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")}); +this.store("send",e);}return e;}};Element.implement({send:function(e){var f=this.get("send");f.send({data:this,url:e||f.options.url});return this;}});})(); +Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false,headers:{Accept:"text/html, application/xml, text/xml, */*"}},success:function(f){var e=this.options,c=this.response; +c.html=f.stripScripts(function(h){c.javascript=h;});var d=c.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);if(d){c.html=d[1];}var b=new Element("div").set("html",c.html); +c.tree=b.childNodes;c.elements=b.getElements(e.filter||"*");if(e.filter){c.tree=c.elements;}if(e.update){var g=document.id(e.update).empty();if(e.filter){g.adopt(c.elements); +}else{g.set("html",c.html);}}else{if(e.append){var a=document.id(e.append);if(e.filter){c.elements.reverse().inject(a);}else{a.adopt(b.getChildren());}}}if(e.evalScripts){Browser.exec(c.javascript); +}this.onSuccess(c.tree,c.elements,c.html,c.javascript);}});Element.Properties.load={set:function(a){var b=this.get("load").cancel();b.setOptions(a);return this; +},get:function(){var a=this.retrieve("load");if(!a){a=new Request.HTML({data:this,link:"cancel",update:this,method:"get"});this.store("load",a);}return a; +}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Type.isObject,url:Type.isString}));return this;}});if(typeof JSON=="undefined"){this.JSON={}; +}(function(){var special={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};var escape=function(chr){return special[chr]||"\\u"+("0000"+chr.charCodeAt(0).toString(16)).slice(-4); +};JSON.validate=function(string){string=string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""); +return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON(); +}switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[]; +Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj; +case"null":return"null";}return null;};JSON.secure=true;JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure==null){secure=JSON.secure; +}if(secure){if(JSON.parse){return JSON.parse(string);}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure."); +}}return eval("("+string+")");};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"}); +},success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure(); +}else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b; +this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path; +}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure"; +}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)"); +return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,Object.merge({},this.options,{duration:-1})).write("");return this;}}); +Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose(); +};(function(i,k){var l,f,e=[],c,b,d=k.createElement("div");var g=function(){clearTimeout(b);if(l){return;}Browser.loaded=l=true;k.removeListener("DOMContentLoaded",g).removeListener("readystatechange",a); +k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.length;m--;){if(e[m]()){g();return true;}}return false;};var j=function(){clearTimeout(b); +if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h); +c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a); +}else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this); +}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);
\ No newline at end of file diff --git a/module/webui/themes/default/js/static/mootools-more.js b/module/webui/themes/default/js/static/mootools-more.js new file mode 100644 index 000000000..c7f4a1a0e --- /dev/null +++ b/module/webui/themes/default/js/static/mootools-more.js @@ -0,0 +1,2856 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/more/c1cc18c2fff04bcc58921b4dff80a6f1 + +packager build: + - packager build More/Form.Request More/Fx.Reveal More/Sortables More/Request.Periodical More/Color + +... +*/ + +/* +--- + +script: More.js + +name: More + +description: MooTools More + +license: MIT-style license + +authors: + - Guillermo Rauch + - Thomas Aylott + - Scott Kyle + - Arian Stolwijk + - Tim Wienk + - Christoph Pojer + - Aaron Newton + - Jacob Thornton + +requires: + - Core/MooTools + +provides: [MooTools.More] + +... +*/ + +MooTools.More = { + version: '1.5.0', + build: '73db5e24e6e9c5c87b3a27aebef2248053f7db37' +}; + + +/* +--- + +script: Class.Binds.js + +name: Class.Binds + +description: Automagically binds specified methods in a class to the instance of the class. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - MooTools.More + +provides: [Class.Binds] + +... +*/ + +Class.Mutators.Binds = function(binds){ + if (!this.prototype.initialize) this.implement('initialize', function(){}); + return Array.from(binds).concat(this.prototype.Binds || []); +}; + +Class.Mutators.initialize = function(initialize){ + return function(){ + Array.from(this.Binds).each(function(name){ + var original = this[name]; + if (original) this[name] = original.bind(this); + }, this); + return initialize.apply(this, arguments); + }; +}; + + +/* +--- + +script: Class.Occlude.js + +name: Class.Occlude + +description: Prevents a class from being applied to a DOM element twice. + +license: MIT-style license. + +authors: + - Aaron Newton + +requires: + - Core/Class + - Core/Element + - MooTools.More + +provides: [Class.Occlude] + +... +*/ + +Class.Occlude = new Class({ + + occlude: function(property, element){ + element = document.id(element || this.element); + var instance = element.retrieve(property || this.property); + if (instance && !this.occluded) + return (this.occluded = instance); + + this.occluded = false; + element.store(property || this.property, this); + return this.occluded; + } + +}); + + +/* +--- + +script: Class.Refactor.js + +name: Class.Refactor + +description: Extends a class onto itself with new property, preserving any items attached to the class's namespace. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - MooTools.More + +# Some modules declare themselves dependent on Class.Refactor +provides: [Class.refactor, Class.Refactor] + +... +*/ + +Class.refactor = function(original, refactors){ + + Object.each(refactors, function(item, name){ + var origin = original.prototype[name]; + origin = (origin && origin.$origin) || origin || function(){}; + original.implement(name, (typeof item == 'function') ? function(){ + var old = this.previous; + this.previous = origin; + var value = item.apply(this, arguments); + this.previous = old; + return value; + } : item); + }); + + return original; + +}; + + +/* +--- + +script: Element.Measure.js + +name: Element.Measure + +description: Extends the Element native object to include methods useful in measuring dimensions. + +credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz" + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - Core/Element.Dimensions + - MooTools.More + +provides: [Element.Measure] + +... +*/ + +(function(){ + +var getStylesList = function(styles, planes){ + var list = []; + Object.each(planes, function(directions){ + Object.each(directions, function(edge){ + styles.each(function(style){ + list.push(style + '-' + edge + (style == 'border' ? '-width' : '')); + }); + }); + }); + return list; +}; + +var calculateEdgeSize = function(edge, styles){ + var total = 0; + Object.each(styles, function(value, style){ + if (style.test(edge)) total = total + value.toInt(); + }); + return total; +}; + +var isVisible = function(el){ + return !!(!el || el.offsetHeight || el.offsetWidth); +}; + + +Element.implement({ + + measure: function(fn){ + if (isVisible(this)) return fn.call(this); + var parent = this.getParent(), + toMeasure = []; + while (!isVisible(parent) && parent != document.body){ + toMeasure.push(parent.expose()); + parent = parent.getParent(); + } + var restore = this.expose(), + result = fn.call(this); + restore(); + toMeasure.each(function(restore){ + restore(); + }); + return result; + }, + + expose: function(){ + if (this.getStyle('display') != 'none') return function(){}; + var before = this.style.cssText; + this.setStyles({ + display: 'block', + position: 'absolute', + visibility: 'hidden' + }); + return function(){ + this.style.cssText = before; + }.bind(this); + }, + + getDimensions: function(options){ + options = Object.merge({computeSize: false}, options); + var dim = {x: 0, y: 0}; + + var getSize = function(el, options){ + return (options.computeSize) ? el.getComputedSize(options) : el.getSize(); + }; + + var parent = this.getParent('body'); + + if (parent && this.getStyle('display') == 'none'){ + dim = this.measure(function(){ + return getSize(this, options); + }); + } else if (parent){ + try { //safari sometimes crashes here, so catch it + dim = getSize(this, options); + }catch(e){} + } + + return Object.append(dim, (dim.x || dim.x === 0) ? { + width: dim.x, + height: dim.y + } : { + x: dim.width, + y: dim.height + } + ); + }, + + getComputedSize: function(options){ + + + options = Object.merge({ + styles: ['padding','border'], + planes: { + height: ['top','bottom'], + width: ['left','right'] + }, + mode: 'both' + }, options); + + var styles = {}, + size = {width: 0, height: 0}, + dimensions; + + if (options.mode == 'vertical'){ + delete size.width; + delete options.planes.width; + } else if (options.mode == 'horizontal'){ + delete size.height; + delete options.planes.height; + } + + getStylesList(options.styles, options.planes).each(function(style){ + styles[style] = this.getStyle(style).toInt(); + }, this); + + Object.each(options.planes, function(edges, plane){ + + var capitalized = plane.capitalize(), + style = this.getStyle(plane); + + if (style == 'auto' && !dimensions) dimensions = this.getDimensions(); + + style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt(); + size['total' + capitalized] = style; + + edges.each(function(edge){ + var edgesize = calculateEdgeSize(edge, styles); + size['computed' + edge.capitalize()] = edgesize; + size['total' + capitalized] += edgesize; + }); + + }, this); + + return Object.append(size, styles); + } + +}); + +})(); + + +/* +--- + +script: Element.Position.js + +name: Element.Position + +description: Extends the Element native object to include methods useful positioning elements relative to others. + +license: MIT-style license + +authors: + - Aaron Newton + - Jacob Thornton + +requires: + - Core/Options + - Core/Element.Dimensions + - Element.Measure + +provides: [Element.Position] + +... +*/ + +(function(original){ + +var local = Element.Position = { + + options: {/* + edge: false, + returnPos: false, + minimum: {x: 0, y: 0}, + maximum: {x: 0, y: 0}, + relFixedPosition: false, + ignoreMargins: false, + ignoreScroll: false, + allowNegative: false,*/ + relativeTo: document.body, + position: { + x: 'center', //left, center, right + y: 'center' //top, center, bottom + }, + offset: {x: 0, y: 0} + }, + + getOptions: function(element, options){ + options = Object.merge({}, local.options, options); + local.setPositionOption(options); + local.setEdgeOption(options); + local.setOffsetOption(element, options); + local.setDimensionsOption(element, options); + return options; + }, + + setPositionOption: function(options){ + options.position = local.getCoordinateFromValue(options.position); + }, + + setEdgeOption: function(options){ + var edgeOption = local.getCoordinateFromValue(options.edge); + options.edge = edgeOption ? edgeOption : + (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} : + {x: 'left', y: 'top'}; + }, + + setOffsetOption: function(element, options){ + var parentOffset = {x: 0, y: 0}; + var parentScroll = {x: 0, y: 0}; + var offsetParent = element.measure(function(){ + return document.id(this.getOffsetParent()); + }); + + if (!offsetParent || offsetParent == element.getDocument().body) return; + + parentScroll = offsetParent.getScroll(); + parentOffset = offsetParent.measure(function(){ + var position = this.getPosition(); + if (this.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.x += scroll.x; + position.y += scroll.y; + } + return position; + }); + + options.offset = { + parentPositioned: offsetParent != document.id(options.relativeTo), + x: options.offset.x - parentOffset.x + parentScroll.x, + y: options.offset.y - parentOffset.y + parentScroll.y + }; + }, + + setDimensionsOption: function(element, options){ + options.dimensions = element.getDimensions({ + computeSize: true, + styles: ['padding', 'border', 'margin'] + }); + }, + + getPosition: function(element, options){ + var position = {}; + options = local.getOptions(element, options); + var relativeTo = document.id(options.relativeTo) || document.body; + + local.setPositionCoordinates(options, position, relativeTo); + if (options.edge) local.toEdge(position, options); + + var offset = options.offset; + position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt(); + position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt(); + + local.toMinMax(position, options); + + if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position); + if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position); + if (options.ignoreMargins) local.toIgnoreMargins(position, options); + + position.left = Math.ceil(position.left); + position.top = Math.ceil(position.top); + delete position.x; + delete position.y; + + return position; + }, + + setPositionCoordinates: function(options, position, relativeTo){ + var offsetY = options.offset.y, + offsetX = options.offset.x, + calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(), + top = calc.y, + left = calc.x, + winSize = window.getSize(); + + switch(options.position.x){ + case 'left': position.x = left + offsetX; break; + case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break; + default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break; + } + + switch(options.position.y){ + case 'top': position.y = top + offsetY; break; + case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break; + default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break; + } + }, + + toMinMax: function(position, options){ + var xy = {left: 'x', top: 'y'}, value; + ['minimum', 'maximum'].each(function(minmax){ + ['left', 'top'].each(function(lr){ + value = options[minmax] ? options[minmax][xy[lr]] : null; + if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value; + }); + }); + }, + + toRelFixedPosition: function(relativeTo, position){ + var winScroll = window.getScroll(); + position.top += winScroll.y; + position.left += winScroll.x; + }, + + toIgnoreScroll: function(relativeTo, position){ + var relScroll = relativeTo.getScroll(); + position.top -= relScroll.y; + position.left -= relScroll.x; + }, + + toIgnoreMargins: function(position, options){ + position.left += options.edge.x == 'right' + ? options.dimensions['margin-right'] + : (options.edge.x != 'center' + ? -options.dimensions['margin-left'] + : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2)); + + position.top += options.edge.y == 'bottom' + ? options.dimensions['margin-bottom'] + : (options.edge.y != 'center' + ? -options.dimensions['margin-top'] + : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2)); + }, + + toEdge: function(position, options){ + var edgeOffset = {}, + dimensions = options.dimensions, + edge = options.edge; + + switch(edge.x){ + case 'left': edgeOffset.x = 0; break; + case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break; + // center + default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break; + } + + switch(edge.y){ + case 'top': edgeOffset.y = 0; break; + case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break; + // center + default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break; + } + + position.x += edgeOffset.x; + position.y += edgeOffset.y; + }, + + getCoordinateFromValue: function(option){ + if (typeOf(option) != 'string') return option; + option = option.toLowerCase(); + + return { + x: option.test('left') ? 'left' + : (option.test('right') ? 'right' : 'center'), + y: option.test(/upper|top/) ? 'top' + : (option.test('bottom') ? 'bottom' : 'center') + }; + } + +}; + +Element.implement({ + + position: function(options){ + if (options && (options.x != null || options.y != null)){ + return (original ? original.apply(this, arguments) : this); + } + var position = this.setStyle('position', 'absolute').calculatePosition(options); + return (options && options.returnPos) ? position : this.setStyles(position); + }, + + calculatePosition: function(options){ + return local.getPosition(this, options); + } + +}); + +})(Element.prototype.position); + + +/* +--- + +script: IframeShim.js + +name: IframeShim + +description: Defines IframeShim, a class for obscuring select lists and flash objects in IE. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Event + - Core/Element.Style + - Core/Options + - Core/Events + - Element.Position + - Class.Occlude + +provides: [IframeShim] + +... +*/ + +(function(){ + +var browsers = false; + + +this.IframeShim = new Class({ + + Implements: [Options, Events, Class.Occlude], + + options: { + className: 'iframeShim', + src: 'javascript:false;document.write("");', + display: false, + zIndex: null, + margin: 0, + offset: {x: 0, y: 0}, + browsers: browsers + }, + + property: 'IframeShim', + + initialize: function(element, options){ + this.element = document.id(element); + if (this.occlude()) return this.occluded; + this.setOptions(options); + this.makeShim(); + return this; + }, + + makeShim: function(){ + if (this.options.browsers){ + var zIndex = this.element.getStyle('zIndex').toInt(); + + if (!zIndex){ + zIndex = 1; + var pos = this.element.getStyle('position'); + if (pos == 'static' || !pos) this.element.setStyle('position', 'relative'); + this.element.setStyle('zIndex', zIndex); + } + zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1; + if (zIndex < 0) zIndex = 1; + this.shim = new Element('iframe', { + src: this.options.src, + scrolling: 'no', + frameborder: 0, + styles: { + zIndex: zIndex, + position: 'absolute', + border: 'none', + filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)' + }, + 'class': this.options.className + }).store('IframeShim', this); + var inject = (function(){ + this.shim.inject(this.element, 'after'); + this[this.options.display ? 'show' : 'hide'](); + this.fireEvent('inject'); + }).bind(this); + if (!IframeShim.ready) window.addEvent('load', inject); + else inject(); + } else { + this.position = this.hide = this.show = this.dispose = Function.from(this); + } + }, + + position: function(){ + if (!IframeShim.ready || !this.shim) return this; + var size = this.element.measure(function(){ + return this.getSize(); + }); + if (this.options.margin != undefined){ + size.x = size.x - (this.options.margin * 2); + size.y = size.y - (this.options.margin * 2); + this.options.offset.x += this.options.margin; + this.options.offset.y += this.options.margin; + } + this.shim.set({width: size.x, height: size.y}).position({ + relativeTo: this.element, + offset: this.options.offset + }); + return this; + }, + + hide: function(){ + if (this.shim) this.shim.setStyle('display', 'none'); + return this; + }, + + show: function(){ + if (this.shim) this.shim.setStyle('display', 'block'); + return this.position(); + }, + + dispose: function(){ + if (this.shim) this.shim.dispose(); + return this; + }, + + destroy: function(){ + if (this.shim) this.shim.destroy(); + return this; + } + +}); + +})(); + +window.addEvent('load', function(){ + IframeShim.ready = true; +}); + + +/* +--- + +script: Mask.js + +name: Mask + +description: Creates a mask element to cover another. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Options + - Core/Events + - Core/Element.Event + - Class.Binds + - Element.Position + - IframeShim + +provides: [Mask] + +... +*/ + +var Mask = new Class({ + + Implements: [Options, Events], + + Binds: ['position'], + + options: {/* + onShow: function(){}, + onHide: function(){}, + onDestroy: function(){}, + onClick: function(event){}, + inject: { + where: 'after', + target: null, + }, + hideOnClick: false, + id: null, + destroyOnHide: false,*/ + style: {}, + 'class': 'mask', + maskMargins: false, + useIframeShim: true, + iframeShimOptions: {} + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('mask', this); + this.setOptions(options); + this.render(); + this.inject(); + }, + + render: function(){ + this.element = new Element('div', { + 'class': this.options['class'], + id: this.options.id || 'mask-' + String.uniqueID(), + styles: Object.merge({}, this.options.style, { + display: 'none' + }), + events: { + click: function(event){ + this.fireEvent('click', event); + if (this.options.hideOnClick) this.hide(); + }.bind(this) + } + }); + + this.hidden = true; + }, + + toElement: function(){ + return this.element; + }, + + inject: function(target, where){ + where = where || (this.options.inject ? this.options.inject.where : '') || (this.target == document.body ? 'inside' : 'after'); + target = target || (this.options.inject && this.options.inject.target) || this.target; + + this.element.inject(target, where); + + if (this.options.useIframeShim){ + this.shim = new IframeShim(this.element, this.options.iframeShimOptions); + + this.addEvents({ + show: this.shim.show.bind(this.shim), + hide: this.shim.hide.bind(this.shim), + destroy: this.shim.destroy.bind(this.shim) + }); + } + }, + + position: function(){ + this.resize(this.options.width, this.options.height); + + this.element.position({ + relativeTo: this.target, + position: 'topLeft', + ignoreMargins: !this.options.maskMargins, + ignoreScroll: this.target == document.body + }); + + return this; + }, + + resize: function(x, y){ + var opt = { + styles: ['padding', 'border'] + }; + if (this.options.maskMargins) opt.styles.push('margin'); + + var dim = this.target.getComputedSize(opt); + if (this.target == document.body){ + this.element.setStyles({width: 0, height: 0}); + var win = window.getScrollSize(); + if (dim.totalHeight < win.y) dim.totalHeight = win.y; + if (dim.totalWidth < win.x) dim.totalWidth = win.x; + } + this.element.setStyles({ + width: Array.pick([x, dim.totalWidth, dim.x]), + height: Array.pick([y, dim.totalHeight, dim.y]) + }); + + return this; + }, + + show: function(){ + if (!this.hidden) return this; + + window.addEvent('resize', this.position); + this.position(); + this.showMask.apply(this, arguments); + + return this; + }, + + showMask: function(){ + this.element.setStyle('display', 'block'); + this.hidden = false; + this.fireEvent('show'); + }, + + hide: function(){ + if (this.hidden) return this; + + window.removeEvent('resize', this.position); + this.hideMask.apply(this, arguments); + if (this.options.destroyOnHide) return this.destroy(); + + return this; + }, + + hideMask: function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + }, + + toggle: function(){ + this[this.hidden ? 'show' : 'hide'](); + }, + + destroy: function(){ + this.hide(); + this.element.destroy(); + this.fireEvent('destroy'); + this.target.eliminate('mask'); + } + +}); + +Element.Properties.mask = { + + set: function(options){ + var mask = this.retrieve('mask'); + if (mask) mask.destroy(); + return this.eliminate('mask').store('mask:options', options); + }, + + get: function(){ + var mask = this.retrieve('mask'); + if (!mask){ + mask = new Mask(this, this.retrieve('mask:options')); + this.store('mask', mask); + } + return mask; + } + +}; + +Element.implement({ + + mask: function(options){ + if (options) this.set('mask', options); + this.get('mask').show(); + return this; + }, + + unmask: function(){ + this.get('mask').hide(); + return this; + } + +}); + + +/* +--- + +script: Spinner.js + +name: Spinner + +description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Tween + - Core/Request + - Class.refactor + - Mask + +provides: [Spinner] + +... +*/ + +var Spinner = new Class({ + + Extends: Mask, + + Implements: Chain, + + options: {/* + message: false,*/ + 'class': 'spinner', + containerPosition: {}, + content: { + 'class': 'spinner-content' + }, + messageContainer: { + 'class': 'spinner-msg' + }, + img: { + 'class': 'spinner-img' + }, + fxOptions: { + link: 'chain' + } + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('spinner', this); + this.setOptions(options); + this.render(); + this.inject(); + + // Add this to events for when noFx is true; parent methods handle hide/show. + var deactivate = function(){ this.active = false; }.bind(this); + this.addEvents({ + hide: deactivate, + show: deactivate + }); + }, + + render: function(){ + this.parent(); + + this.element.set('id', this.options.id || 'spinner-' + String.uniqueID()); + + this.content = document.id(this.options.content) || new Element('div', this.options.content); + this.content.inject(this.element); + + if (this.options.message){ + this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message); + this.msg.inject(this.content); + } + + if (this.options.img){ + this.img = document.id(this.options.img) || new Element('div', this.options.img); + this.img.inject(this.content); + } + + this.element.set('tween', this.options.fxOptions); + }, + + show: function(noFx){ + if (this.active) return this.chain(this.show.bind(this)); + if (!this.hidden){ + this.callChain.delay(20, this); + return this; + } + + this.target.set('aria-busy', 'true'); + this.active = true; + + return this.parent(noFx); + }, + + showMask: function(noFx){ + var pos = function(){ + this.content.position(Object.merge({ + relativeTo: this.element + }, this.options.containerPosition)); + }.bind(this); + + if (noFx){ + this.parent(); + pos(); + } else { + if (!this.options.style.opacity) this.options.style.opacity = this.element.getStyle('opacity').toFloat(); + this.element.setStyles({ + display: 'block', + opacity: 0 + }).tween('opacity', this.options.style.opacity); + pos(); + this.hidden = false; + this.fireEvent('show'); + this.callChain(); + } + }, + + hide: function(noFx){ + if (this.active) return this.chain(this.hide.bind(this)); + if (this.hidden){ + this.callChain.delay(20, this); + return this; + } + + this.target.set('aria-busy', 'false'); + this.active = true; + + return this.parent(noFx); + }, + + hideMask: function(noFx){ + if (noFx) return this.parent(); + this.element.tween('opacity', 0).get('tween').chain(function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + this.callChain(); + }.bind(this)); + }, + + destroy: function(){ + this.content.destroy(); + this.parent(); + this.target.eliminate('spinner'); + } + +}); + +Request = Class.refactor(Request, { + + options: { + useSpinner: false, + spinnerOptions: {}, + spinnerTarget: false + }, + + initialize: function(options){ + this._send = this.send; + this.send = function(options){ + var spinner = this.getSpinner(); + if (spinner) spinner.chain(this._send.pass(options, this)).show(); + else this._send(options); + return this; + }; + this.previous(options); + }, + + getSpinner: function(){ + if (!this.spinner){ + var update = document.id(this.options.spinnerTarget) || document.id(this.options.update); + if (this.options.useSpinner && update){ + update.set('spinner', this.options.spinnerOptions); + var spinner = this.spinner = update.get('spinner'); + ['complete', 'exception', 'cancel'].each(function(event){ + this.addEvent(event, spinner.hide.bind(spinner)); + }, this); + } + } + return this.spinner; + } + +}); + +Element.Properties.spinner = { + + set: function(options){ + var spinner = this.retrieve('spinner'); + if (spinner) spinner.destroy(); + return this.eliminate('spinner').store('spinner:options', options); + }, + + get: function(){ + var spinner = this.retrieve('spinner'); + if (!spinner){ + spinner = new Spinner(this, this.retrieve('spinner:options')); + this.store('spinner', spinner); + } + return spinner; + } + +}; + +Element.implement({ + + spin: function(options){ + if (options) this.set('spinner', options); + this.get('spinner').show(); + return this; + }, + + unspin: function(){ + this.get('spinner').hide(); + return this; + } + +}); + + +/* +--- + +script: String.QueryString.js + +name: String.QueryString + +description: Methods for dealing with URI query strings. + +license: MIT-style license + +authors: + - Sebastian Markbåge + - Aaron Newton + - Lennart Pilon + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - MooTools.More + +provides: [String.QueryString] + +... +*/ + +String.implement({ + + parseQueryString: function(decodeKeys, decodeValues){ + if (decodeKeys == null) decodeKeys = true; + if (decodeValues == null) decodeValues = true; + + var vars = this.split(/[&;]/), + object = {}; + if (!vars.length) return object; + + vars.each(function(val){ + var index = val.indexOf('=') + 1, + value = index ? val.substr(index) : '', + keys = index ? val.substr(0, index - 1).match(/([^\]\[]+|(\B)(?=\]))/g) : [val], + obj = object; + if (!keys) return; + if (decodeValues) value = decodeURIComponent(value); + keys.each(function(key, i){ + if (decodeKeys) key = decodeURIComponent(key); + var current = obj[key]; + + if (i < keys.length - 1) obj = obj[key] = current || {}; + else if (typeOf(current) == 'array') current.push(value); + else obj[key] = current != null ? [current, value] : value; + }); + }); + + return object; + }, + + cleanQueryString: function(method){ + return this.split('&').filter(function(val){ + var index = val.indexOf('='), + key = index < 0 ? '' : val.substr(0, index), + value = val.substr(index + 1); + + return method ? method.call(null, key, value) : (value || value === 0); + }).join('&'); + } + +}); + + +/* +--- + +name: Events.Pseudos + +description: Adds the functionality to add pseudo events + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Class.Extras, Core/Slick.Parser, MooTools.More] + +provides: [Events.Pseudos] + +... +*/ + +(function(){ + +Events.Pseudos = function(pseudos, addEvent, removeEvent){ + + var storeKey = '_monitorEvents:'; + + var storageOf = function(object){ + return { + store: object.store ? function(key, value){ + object.store(storeKey + key, value); + } : function(key, value){ + (object._monitorEvents || (object._monitorEvents = {}))[key] = value; + }, + retrieve: object.retrieve ? function(key, dflt){ + return object.retrieve(storeKey + key, dflt); + } : function(key, dflt){ + if (!object._monitorEvents) return dflt; + return object._monitorEvents[key] || dflt; + } + }; + }; + + var splitType = function(type){ + if (type.indexOf(':') == -1 || !pseudos) return null; + + var parsed = Slick.parse(type).expressions[0][0], + parsedPseudos = parsed.pseudos, + l = parsedPseudos.length, + splits = []; + + while (l--){ + var pseudo = parsedPseudos[l].key, + listener = pseudos[pseudo]; + if (listener != null) splits.push({ + event: parsed.tag, + value: parsedPseudos[l].value, + pseudo: pseudo, + original: type, + listener: listener + }); + } + return splits.length ? splits : null; + }; + + return { + + addEvent: function(type, fn, internal){ + var split = splitType(type); + if (!split) return addEvent.call(this, type, fn, internal); + + var storage = storageOf(this), + events = storage.retrieve(type, []), + eventType = split[0].event, + args = Array.slice(arguments, 2), + stack = fn, + self = this; + + split.each(function(item){ + var listener = item.listener, + stackFn = stack; + if (listener == false) eventType += ':' + item.pseudo + '(' + item.value + ')'; + else stack = function(){ + listener.call(self, item, stackFn, arguments, stack); + }; + }); + + events.include({type: eventType, event: fn, monitor: stack}); + storage.store(type, events); + + if (type != eventType) addEvent.apply(this, [type, fn].concat(args)); + return addEvent.apply(this, [eventType, stack].concat(args)); + }, + + removeEvent: function(type, fn){ + var split = splitType(type); + if (!split) return removeEvent.call(this, type, fn); + + var storage = storageOf(this), + events = storage.retrieve(type); + if (!events) return this; + + var args = Array.slice(arguments, 2); + + removeEvent.apply(this, [type, fn].concat(args)); + events.each(function(monitor, i){ + if (!fn || monitor.event == fn) removeEvent.apply(this, [monitor.type, monitor.monitor].concat(args)); + delete events[i]; + }, this); + + storage.store(type, events); + return this; + } + + }; + +}; + +var pseudos = { + + once: function(split, fn, args, monitor){ + fn.apply(this, args); + this.removeEvent(split.event, monitor) + .removeEvent(split.original, fn); + }, + + throttle: function(split, fn, args){ + if (!fn._throttled){ + fn.apply(this, args); + fn._throttled = setTimeout(function(){ + fn._throttled = false; + }, split.value || 250); + } + }, + + pause: function(split, fn, args){ + clearTimeout(fn._pause); + fn._pause = fn.delay(split.value || 250, this, args); + } + +}; + +Events.definePseudo = function(key, listener){ + pseudos[key] = listener; + return this; +}; + +Events.lookupPseudo = function(key){ + return pseudos[key]; +}; + +var proto = Events.prototype; +Events.implement(Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +['Request', 'Fx'].each(function(klass){ + if (this[klass]) this[klass].implement(Events.prototype); +}); + +})(); + + +/* +--- + +name: Element.Event.Pseudos + +description: Adds the functionality to add pseudo events for Elements + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Element.Event, Core/Element.Delegation, Events.Pseudos] + +provides: [Element.Event.Pseudos, Element.Delegation.Pseudo] + +... +*/ + +(function(){ + +var pseudos = {relay: false}, + copyFromEvents = ['once', 'throttle', 'pause'], + count = copyFromEvents.length; + +while (count--) pseudos[copyFromEvents[count]] = Events.lookupPseudo(copyFromEvents[count]); + +DOMEvent.definePseudo = function(key, listener){ + pseudos[key] = listener; + return this; +}; + +var proto = Element.prototype; +[Element, Window, Document].invoke('implement', Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +})(); + + +/* +--- + +script: Form.Request.js + +name: Form.Request + +description: Handles the basic functionality of submitting a form and updating a dom element with the result. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Request.HTML + - Class.Binds + - Class.Occlude + - Spinner + - String.QueryString + - Element.Delegation.Pseudo + +provides: [Form.Request] + +... +*/ + +if (!window.Form) window.Form = {}; + +(function(){ + + Form.Request = new Class({ + + Binds: ['onSubmit', 'onFormValidate'], + + Implements: [Options, Events, Class.Occlude], + + options: {/* + onFailure: function(){}, + onSuccess: function(){}, // aliased to onComplete, + onSend: function(){}*/ + requestOptions: { + evalScripts: true, + useSpinner: true, + emulation: false, + link: 'ignore' + }, + sendButtonClicked: true, + extraData: {}, + resetForm: true + }, + + property: 'form.request', + + initialize: function(form, target, options){ + this.element = document.id(form); + if (this.occlude()) return this.occluded; + this.setOptions(options) + .setTarget(target) + .attach(); + }, + + setTarget: function(target){ + this.target = document.id(target); + if (!this.request){ + this.makeRequest(); + } else { + this.request.setOptions({ + update: this.target + }); + } + return this; + }, + + toElement: function(){ + return this.element; + }, + + makeRequest: function(){ + var self = this; + this.request = new Request.HTML(Object.merge({ + update: this.target, + emulation: false, + spinnerTarget: this.element, + method: this.element.get('method') || 'post' + }, this.options.requestOptions)).addEvents({ + success: function(tree, elements, html, javascript){ + ['complete', 'success'].each(function(evt){ + self.fireEvent(evt, [self.target, tree, elements, html, javascript]); + }); + }, + failure: function(){ + self.fireEvent('complete', arguments).fireEvent('failure', arguments); + }, + exception: function(){ + self.fireEvent('failure', arguments); + } + }); + return this.attachReset(); + }, + + attachReset: function(){ + if (!this.options.resetForm) return this; + this.request.addEvent('success', function(){ + Function.attempt(function(){ + this.element.reset(); + }.bind(this)); + if (window.OverText) OverText.update(); + }.bind(this)); + return this; + }, + + attach: function(attach){ + var method = (attach != false) ? 'addEvent' : 'removeEvent'; + this.element[method]('click:relay(button, input[type=submit])', this.saveClickedButton.bind(this)); + + var fv = this.element.retrieve('validator'); + if (fv) fv[method]('onFormValidate', this.onFormValidate); + else this.element[method]('submit', this.onSubmit); + + return this; + }, + + detach: function(){ + return this.attach(false); + }, + + //public method + enable: function(){ + return this.attach(); + }, + + //public method + disable: function(){ + return this.detach(); + }, + + onFormValidate: function(valid, form, event){ + //if there's no event, then this wasn't a submit event + if (!event) return; + var fv = this.element.retrieve('validator'); + if (valid || (fv && !fv.options.stopOnFailure)){ + event.stop(); + this.send(); + } + }, + + onSubmit: function(event){ + var fv = this.element.retrieve('validator'); + if (fv){ + //form validator was created after Form.Request + this.element.removeEvent('submit', this.onSubmit); + fv.addEvent('onFormValidate', this.onFormValidate); + fv.validate(event); + return; + } + if (event) event.stop(); + this.send(); + }, + + saveClickedButton: function(event, target){ + var targetName = target.get('name'); + if (!targetName || !this.options.sendButtonClicked) return; + this.options.extraData[targetName] = target.get('value') || true; + this.clickedCleaner = function(){ + delete this.options.extraData[targetName]; + this.clickedCleaner = function(){}; + }.bind(this); + }, + + clickedCleaner: function(){}, + + send: function(){ + var str = this.element.toQueryString().trim(), + data = Object.toQueryString(this.options.extraData); + + if (str) str += "&" + data; + else str = data; + + this.fireEvent('send', [this.element, str.parseQueryString()]); + this.request.send({ + data: str, + url: this.options.requestOptions.url || this.element.get('action') + }); + this.clickedCleaner(); + return this; + } + + }); + + Element.implement('formUpdate', function(update, options){ + var fq = this.retrieve('form.request'); + if (!fq){ + fq = new Form.Request(this, update, options); + } else { + if (update) fq.setTarget(update); + if (options) fq.setOptions(options).makeRequest(); + } + fq.send(); + return this; + }); + +})(); + + +/* +--- + +script: Element.Shortcuts.js + +name: Element.Shortcuts + +description: Extends the Element native object to include some shortcut methods. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - MooTools.More + +provides: [Element.Shortcuts] + +... +*/ + +Element.implement({ + + isDisplayed: function(){ + return this.getStyle('display') != 'none'; + }, + + isVisible: function(){ + var w = this.offsetWidth, + h = this.offsetHeight; + return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.style.display != 'none'; + }, + + toggle: function(){ + return this[this.isDisplayed() ? 'hide' : 'show'](); + }, + + hide: function(){ + var d; + try { + //IE fails here if the element is not in the dom + d = this.getStyle('display'); + } catch(e){} + if (d == 'none') return this; + return this.store('element:_originalDisplay', d || '').setStyle('display', 'none'); + }, + + show: function(display){ + if (!display && this.isDisplayed()) return this; + display = display || this.retrieve('element:_originalDisplay') || 'block'; + return this.setStyle('display', (display == 'none') ? 'block' : display); + }, + + swapClass: function(remove, add){ + return this.removeClass(remove).addClass(add); + } + +}); + +Document.implement({ + + clearSelection: function(){ + if (window.getSelection){ + var selection = window.getSelection(); + if (selection && selection.removeAllRanges) selection.removeAllRanges(); + } else if (document.selection && document.selection.empty){ + try { + //IE fails here if selected element is not in dom + document.selection.empty(); + } catch(e){} + } + } + +}); + + +/* +--- + +script: Fx.Reveal.js + +name: Fx.Reveal + +description: Defines Fx.Reveal, a class that shows and hides elements with a transition. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Morph + - Element.Shortcuts + - Element.Measure + +provides: [Fx.Reveal] + +... +*/ + +(function(){ + + +var hideTheseOf = function(object){ + var hideThese = object.options.hideInputs; + if (window.OverText){ + var otClasses = [null]; + OverText.each(function(ot){ + otClasses.include('.' + ot.options.labelClass); + }); + if (otClasses) hideThese += otClasses.join(', '); + } + return (hideThese) ? object.element.getElements(hideThese) : null; +}; + + +Fx.Reveal = new Class({ + + Extends: Fx.Morph, + + options: {/* + onShow: function(thisElement){}, + onHide: function(thisElement){}, + onComplete: function(thisElement){}, + heightOverride: null, + widthOverride: null,*/ + link: 'cancel', + styles: ['padding', 'border', 'margin'], + transitionOpacity: 'opacity' in document.documentElement, + mode: 'vertical', + display: function(){ + return this.element.get('tag') != 'tr' ? 'block' : 'table-row'; + }, + opacity: 1, + hideInputs: !('opacity' in document.documentElement) ? 'select, input, textarea, object, embed' : null + }, + + dissolve: function(){ + if (!this.hiding && !this.showing){ + if (this.element.getStyle('display') != 'none'){ + this.hiding = true; + this.showing = false; + this.hidden = true; + this.cssText = this.element.style.cssText; + + var startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + if (this.options.transitionOpacity) startStyles.opacity = this.options.opacity; + + var zero = {}; + Object.each(startStyles, function(style, name){ + zero[name] = [style, 0]; + }); + + this.element.setStyles({ + display: Function.from(this.options.display).call(this), + overflow: 'hidden' + }); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + if (this.hidden){ + this.hiding = false; + this.element.style.cssText = this.cssText; + this.element.setStyle('display', 'none'); + if (hideThese) hideThese.setStyle('visibility', 'visible'); + } + this.fireEvent('hide', this.element); + this.callChain(); + }.bind(this)); + + this.start(zero); + } else { + this.callChain.delay(10, this); + this.fireEvent('complete', this.element); + this.fireEvent('hide', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.dissolve.bind(this)); + } else if (this.options.link == 'cancel' && !this.hiding){ + this.cancel(); + this.dissolve(); + } + return this; + }, + + reveal: function(){ + if (!this.showing && !this.hiding){ + if (this.element.getStyle('display') == 'none'){ + this.hiding = false; + this.showing = true; + this.hidden = false; + this.cssText = this.element.style.cssText; + + var startStyles; + this.element.measure(function(){ + startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + }.bind(this)); + if (this.options.heightOverride != null) startStyles.height = this.options.heightOverride.toInt(); + if (this.options.widthOverride != null) startStyles.width = this.options.widthOverride.toInt(); + if (this.options.transitionOpacity){ + this.element.setStyle('opacity', 0); + startStyles.opacity = this.options.opacity; + } + + var zero = { + height: 0, + display: Function.from(this.options.display).call(this) + }; + Object.each(startStyles, function(style, name){ + zero[name] = 0; + }); + zero.overflow = 'hidden'; + + this.element.setStyles(zero); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + this.element.style.cssText = this.cssText; + this.element.setStyle('display', Function.from(this.options.display).call(this)); + if (!this.hidden) this.showing = false; + if (hideThese) hideThese.setStyle('visibility', 'visible'); + this.callChain(); + this.fireEvent('show', this.element); + }.bind(this)); + + this.start(startStyles); + } else { + this.callChain(); + this.fireEvent('complete', this.element); + this.fireEvent('show', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.reveal.bind(this)); + } else if (this.options.link == 'cancel' && !this.showing){ + this.cancel(); + this.reveal(); + } + return this; + }, + + toggle: function(){ + if (this.element.getStyle('display') == 'none'){ + this.reveal(); + } else { + this.dissolve(); + } + return this; + }, + + cancel: function(){ + this.parent.apply(this, arguments); + if (this.cssText != null) this.element.style.cssText = this.cssText; + this.hiding = false; + this.showing = false; + return this; + } + +}); + +Element.Properties.reveal = { + + set: function(options){ + this.get('reveal').cancel().setOptions(options); + return this; + }, + + get: function(){ + var reveal = this.retrieve('reveal'); + if (!reveal){ + reveal = new Fx.Reveal(this); + this.store('reveal', reveal); + } + return reveal; + } + +}; + +Element.Properties.dissolve = Element.Properties.reveal; + +Element.implement({ + + reveal: function(options){ + this.get('reveal').setOptions(options).reveal(); + return this; + }, + + dissolve: function(options){ + this.get('reveal').setOptions(options).dissolve(); + return this; + }, + + nix: function(options){ + var params = Array.link(arguments, {destroy: Type.isBoolean, options: Type.isObject}); + this.get('reveal').setOptions(options).dissolve().chain(function(){ + this[params.destroy ? 'destroy' : 'dispose'](); + }.bind(this)); + return this; + }, + + wink: function(){ + var params = Array.link(arguments, {duration: Type.isNumber, options: Type.isObject}); + var reveal = this.get('reveal').setOptions(params.options); + reveal.reveal().chain(function(){ + (function(){ + reveal.dissolve(); + }).delay(params.duration || 2000); + }); + } + +}); + +})(); + + +/* +--- + +script: Drag.js + +name: Drag + +description: The base Drag Class. Can be used to drag and resize Elements using mouse events. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + +requires: + - Core/Events + - Core/Options + - Core/Element.Event + - Core/Element.Style + - Core/Element.Dimensions + - MooTools.More + +provides: [Drag] +... + +*/ + +var Drag = new Class({ + + Implements: [Events, Options], + + options: {/* + onBeforeStart: function(thisElement){}, + onStart: function(thisElement, event){}, + onSnap: function(thisElement){}, + onDrag: function(thisElement, event){}, + onCancel: function(thisElement){}, + onComplete: function(thisElement, event){},*/ + snap: 6, + unit: 'px', + grid: false, + style: true, + limit: false, + handle: false, + invert: false, + preventDefault: false, + stopPropagation: false, + modifiers: {x: 'left', y: 'top'} + }, + + initialize: function(){ + var params = Array.link(arguments, { + 'options': Type.isObject, + 'element': function(obj){ + return obj != null; + } + }); + + this.element = document.id(params.element); + this.document = this.element.getDocument(); + this.setOptions(params.options || {}); + var htype = typeOf(this.options.handle); + this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element; + this.mouse = {'now': {}, 'pos': {}}; + this.value = {'start': {}, 'now': {}}; + + this.selection = 'selectstart' in document ? 'selectstart' : 'mousedown'; + + + if ('ondragstart' in document && !('FileReader' in window) && !Drag.ondragstartFixed){ + document.ondragstart = Function.from(false); + Drag.ondragstartFixed = true; + } + + this.bound = { + start: this.start.bind(this), + check: this.check.bind(this), + drag: this.drag.bind(this), + stop: this.stop.bind(this), + cancel: this.cancel.bind(this), + eventStop: Function.from(false) + }; + this.attach(); + }, + + attach: function(){ + this.handles.addEvent('mousedown', this.bound.start); + return this; + }, + + detach: function(){ + this.handles.removeEvent('mousedown', this.bound.start); + return this; + }, + + start: function(event){ + var options = this.options; + + if (event.rightClick) return; + + if (options.preventDefault) event.preventDefault(); + if (options.stopPropagation) event.stopPropagation(); + this.mouse.start = event.page; + + this.fireEvent('beforeStart', this.element); + + var limit = options.limit; + this.limit = {x: [], y: []}; + + var z, coordinates; + for (z in options.modifiers){ + if (!options.modifiers[z]) continue; + + var style = this.element.getStyle(options.modifiers[z]); + + // Some browsers (IE and Opera) don't always return pixels. + if (style && !style.match(/px$/)){ + if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent()); + style = coordinates[options.modifiers[z]]; + } + + if (options.style) this.value.now[z] = (style || 0).toInt(); + else this.value.now[z] = this.element[options.modifiers[z]]; + + if (options.invert) this.value.now[z] *= -1; + + this.mouse.pos[z] = event.page[z] - this.value.now[z]; + + if (limit && limit[z]){ + var i = 2; + while (i--){ + var limitZI = limit[z][i]; + if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI; + } + } + } + + if (typeOf(this.options.grid) == 'number') this.options.grid = { + x: this.options.grid, + y: this.options.grid + }; + + var events = { + mousemove: this.bound.check, + mouseup: this.bound.cancel + }; + events[this.selection] = this.bound.eventStop; + this.document.addEvents(events); + }, + + check: function(event){ + if (this.options.preventDefault) event.preventDefault(); + var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2))); + if (distance > this.options.snap){ + this.cancel(); + this.document.addEvents({ + mousemove: this.bound.drag, + mouseup: this.bound.stop + }); + this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element); + } + }, + + drag: function(event){ + var options = this.options; + + if (options.preventDefault) event.preventDefault(); + this.mouse.now = event.page; + + for (var z in options.modifiers){ + if (!options.modifiers[z]) continue; + this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; + + if (options.invert) this.value.now[z] *= -1; + + if (options.limit && this.limit[z]){ + if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){ + this.value.now[z] = this.limit[z][1]; + } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){ + this.value.now[z] = this.limit[z][0]; + } + } + + if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]); + + if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit); + else this.element[options.modifiers[z]] = this.value.now[z]; + } + + this.fireEvent('drag', [this.element, event]); + }, + + cancel: function(event){ + this.document.removeEvents({ + mousemove: this.bound.check, + mouseup: this.bound.cancel + }); + if (event){ + this.document.removeEvent(this.selection, this.bound.eventStop); + this.fireEvent('cancel', this.element); + } + }, + + stop: function(event){ + var events = { + mousemove: this.bound.drag, + mouseup: this.bound.stop + }; + events[this.selection] = this.bound.eventStop; + this.document.removeEvents(events); + if (event) this.fireEvent('complete', [this.element, event]); + } + +}); + +Element.implement({ + + makeResizable: function(options){ + var drag = new Drag(this, Object.merge({ + modifiers: { + x: 'width', + y: 'height' + } + }, options)); + + this.store('resizer', drag); + return drag.addEvent('drag', function(){ + this.fireEvent('resize', drag); + }.bind(this)); + } + +}); + + +/* +--- + +script: Drag.Move.js + +name: Drag.Move + +description: A Drag extension that provides support for the constraining of draggables to containers and droppables. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + - Aaron Newton + - Scott Kyle + +requires: + - Core/Element.Dimensions + - Drag + +provides: [Drag.Move] + +... +*/ + +Drag.Move = new Class({ + + Extends: Drag, + + options: {/* + onEnter: function(thisElement, overed){}, + onLeave: function(thisElement, overed){}, + onDrop: function(thisElement, overed, event){},*/ + droppables: [], + container: false, + precalculate: false, + includeMargins: true, + checkDroppables: true + }, + + initialize: function(element, options){ + this.parent(element, options); + element = this.element; + + this.droppables = $$(this.options.droppables); + this.setContainer(this.options.container); + + if (this.options.style){ + if (this.options.modifiers.x == 'left' && this.options.modifiers.y == 'top'){ + var parent = element.getOffsetParent(), + styles = element.getStyles('left', 'top'); + if (parent && (styles.left == 'auto' || styles.top == 'auto')){ + element.setPosition(element.getPosition(parent)); + } + } + + if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute'); + } + + this.addEvent('start', this.checkDroppables, true); + this.overed = null; + }, + + setContainer: function(container) { + this.container = document.id(container); + if (this.container && typeOf(this.container) != 'element'){ + this.container = document.id(this.container.getDocument().body); + } + }, + + start: function(event){ + if (this.container) this.options.limit = this.calculateLimit(); + + if (this.options.precalculate){ + this.positions = this.droppables.map(function(el){ + return el.getCoordinates(); + }); + } + + this.parent(event); + }, + + calculateLimit: function(){ + var element = this.element, + container = this.container, + + offsetParent = document.id(element.getOffsetParent()) || document.body, + containerCoordinates = container.getCoordinates(offsetParent), + elementMargin = {}, + elementBorder = {}, + containerMargin = {}, + containerBorder = {}, + offsetParentPadding = {}; + + ['top', 'right', 'bottom', 'left'].each(function(pad){ + elementMargin[pad] = element.getStyle('margin-' + pad).toInt(); + elementBorder[pad] = element.getStyle('border-' + pad).toInt(); + containerMargin[pad] = container.getStyle('margin-' + pad).toInt(); + containerBorder[pad] = container.getStyle('border-' + pad).toInt(); + offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt(); + }, this); + + var width = element.offsetWidth + elementMargin.left + elementMargin.right, + height = element.offsetHeight + elementMargin.top + elementMargin.bottom, + left = 0, + top = 0, + right = containerCoordinates.right - containerBorder.right - width, + bottom = containerCoordinates.bottom - containerBorder.bottom - height; + + if (this.options.includeMargins){ + left += elementMargin.left; + top += elementMargin.top; + } else { + right += elementMargin.right; + bottom += elementMargin.bottom; + } + + if (element.getStyle('position') == 'relative'){ + var coords = element.getCoordinates(offsetParent); + coords.left -= element.getStyle('left').toInt(); + coords.top -= element.getStyle('top').toInt(); + + left -= coords.left; + top -= coords.top; + if (container.getStyle('position') != 'relative'){ + left += containerBorder.left; + top += containerBorder.top; + } + right += elementMargin.left - coords.left; + bottom += elementMargin.top - coords.top; + + if (container != offsetParent){ + left += containerMargin.left + offsetParentPadding.left; + if (!offsetParentPadding.left && left < 0) left = 0; + top += offsetParent == document.body ? 0 : containerMargin.top + offsetParentPadding.top; + if (!offsetParentPadding.top && top < 0) top = 0; + } + } else { + left -= elementMargin.left; + top -= elementMargin.top; + if (container != offsetParent){ + left += containerCoordinates.left + containerBorder.left; + top += containerCoordinates.top + containerBorder.top; + } + } + + return { + x: [left, right], + y: [top, bottom] + }; + }, + + getDroppableCoordinates: function(element){ + var position = element.getCoordinates(); + if (element.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.left += scroll.x; + position.right += scroll.x; + position.top += scroll.y; + position.bottom += scroll.y; + } + return position; + }, + + checkDroppables: function(){ + var overed = this.droppables.filter(function(el, i){ + el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el); + var now = this.mouse.now; + return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top); + }, this).getLast(); + + if (this.overed != overed){ + if (this.overed) this.fireEvent('leave', [this.element, this.overed]); + if (overed) this.fireEvent('enter', [this.element, overed]); + this.overed = overed; + } + }, + + drag: function(event){ + this.parent(event); + if (this.options.checkDroppables && this.droppables.length) this.checkDroppables(); + }, + + stop: function(event){ + this.checkDroppables(); + this.fireEvent('drop', [this.element, this.overed, event]); + this.overed = null; + return this.parent(event); + } + +}); + +Element.implement({ + + makeDraggable: function(options){ + var drag = new Drag.Move(this, options); + this.store('dragger', drag); + return drag; + } + +}); + + +/* +--- + +script: Sortables.js + +name: Sortables + +description: Class for creating a drag and drop sorting interface for lists of items. + +license: MIT-style license + +authors: + - Tom Occhino + +requires: + - Core/Fx.Morph + - Drag.Move + +provides: [Sortables] + +... +*/ + +var Sortables = new Class({ + + Implements: [Events, Options], + + options: {/* + onSort: function(element, clone){}, + onStart: function(element, clone){}, + onComplete: function(element){},*/ + opacity: 1, + clone: false, + revert: false, + handle: false, + dragOptions: {}, + unDraggableTags: ['button', 'input', 'a', 'textarea', 'select', 'option'] + }, + + initialize: function(lists, options){ + this.setOptions(options); + + this.elements = []; + this.lists = []; + this.idle = true; + + this.addLists($$(document.id(lists) || lists)); + + if (!this.options.clone) this.options.revert = false; + if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({ + duration: 250, + link: 'cancel' + }, this.options.revert)); + }, + + attach: function(){ + this.addLists(this.lists); + return this; + }, + + detach: function(){ + this.lists = this.removeLists(this.lists); + return this; + }, + + addItems: function(){ + Array.flatten(arguments).each(function(element){ + this.elements.push(element); + var start = element.retrieve('sortables:start', function(event){ + this.start.call(this, event, element); + }.bind(this)); + (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start); + }, this); + return this; + }, + + addLists: function(){ + Array.flatten(arguments).each(function(list){ + this.lists.include(list); + this.addItems(list.getChildren()); + }, this); + return this; + }, + + removeItems: function(){ + return $$(Array.flatten(arguments).map(function(element){ + this.elements.erase(element); + var start = element.retrieve('sortables:start'); + (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start); + + return element; + }, this)); + }, + + removeLists: function(){ + return $$(Array.flatten(arguments).map(function(list){ + this.lists.erase(list); + this.removeItems(list.getChildren()); + + return list; + }, this)); + }, + + getDroppableCoordinates: function (element){ + var offsetParent = element.getOffsetParent(); + var position = element.getPosition(offsetParent); + var scroll = { + w: window.getScroll(), + offsetParent: offsetParent.getScroll() + }; + position.x += scroll.offsetParent.x; + position.y += scroll.offsetParent.y; + + if (offsetParent.getStyle('position') == 'fixed'){ + position.x -= scroll.w.x; + position.y -= scroll.w.y; + } + + return position; + }, + + getClone: function(event, element){ + if (!this.options.clone) return new Element(element.tagName).inject(document.body); + if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list); + var clone = element.clone(true).setStyles({ + margin: 0, + position: 'absolute', + visibility: 'hidden', + width: element.getStyle('width') + }).addEvent('mousedown', function(event){ + element.fireEvent('mousedown', event); + }); + //prevent the duplicated radio inputs from unchecking the real one + if (clone.get('html').test('radio')){ + clone.getElements('input[type=radio]').each(function(input, i){ + input.set('name', 'clone_' + i); + if (input.get('checked')) element.getElements('input[type=radio]')[i].set('checked', true); + }); + } + + return clone.inject(this.list).setPosition(this.getDroppableCoordinates(this.element)); + }, + + getDroppables: function(){ + var droppables = this.list.getChildren().erase(this.clone).erase(this.element); + if (!this.options.constrain) droppables.append(this.lists).erase(this.list); + return droppables; + }, + + insert: function(dragging, element){ + var where = 'inside'; + if (this.lists.contains(element)){ + this.list = element; + this.drag.droppables = this.getDroppables(); + } else { + where = this.element.getAllPrevious().contains(element) ? 'before' : 'after'; + } + this.element.inject(element, where); + this.fireEvent('sort', [this.element, this.clone]); + }, + + start: function(event, element){ + if ( + !this.idle || + event.rightClick || + (!this.options.handle && this.options.unDraggableTags.contains(event.target.get('tag'))) + ) return; + + this.idle = false; + this.element = element; + this.opacity = element.getStyle('opacity'); + this.list = element.getParent(); + this.clone = this.getClone(event, element); + + this.drag = new Drag.Move(this.clone, Object.merge({ + + droppables: this.getDroppables() + }, this.options.dragOptions)).addEvents({ + onSnap: function(){ + event.stop(); + this.clone.setStyle('visibility', 'visible'); + this.element.setStyle('opacity', this.options.opacity || 0); + this.fireEvent('start', [this.element, this.clone]); + }.bind(this), + onEnter: this.insert.bind(this), + onCancel: this.end.bind(this), + onComplete: this.end.bind(this) + }); + + this.clone.inject(this.element, 'before'); + this.drag.start(event); + }, + + end: function(){ + this.drag.detach(); + this.element.setStyle('opacity', this.opacity); + var self = this; + if (this.effect){ + var dim = this.element.getStyles('width', 'height'), + clone = this.clone, + pos = clone.computePosition(this.getDroppableCoordinates(clone)); + + var destroy = function(){ + this.removeEvent('cancel', destroy); + clone.destroy(); + self.reset(); + }; + + this.effect.element = clone; + this.effect.start({ + top: pos.top, + left: pos.left, + width: dim.width, + height: dim.height, + opacity: 0.25 + }).addEvent('cancel', destroy).chain(destroy); + } else { + this.clone.destroy(); + self.reset(); + } + + }, + + reset: function(){ + this.idle = true; + this.fireEvent('complete', this.element); + }, + + serialize: function(){ + var params = Array.link(arguments, { + modifier: Type.isFunction, + index: function(obj){ + return obj != null; + } + }); + var serial = this.lists.map(function(list){ + return list.getChildren().map(params.modifier || function(element){ + return element.get('id'); + }, this); + }, this); + + var index = params.index; + if (this.lists.length == 1) index = 0; + return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial; + } + +}); + + +/* +--- + +script: Request.Periodical.js + +name: Request.Periodical + +description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load + +license: MIT-style license + +authors: + - Christoph Pojer + +requires: + - Core/Request + - MooTools.More + +provides: [Request.Periodical] + +... +*/ + +Request.implement({ + + options: { + initialDelay: 5000, + delay: 5000, + limit: 60000 + }, + + startTimer: function(data){ + var fn = function(){ + if (!this.running) this.send({data: data}); + }; + this.lastDelay = this.options.initialDelay; + this.timer = fn.delay(this.lastDelay, this); + this.completeCheck = function(response){ + clearTimeout(this.timer); + this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit); + this.timer = fn.delay(this.lastDelay, this); + }; + return this.addEvent('complete', this.completeCheck); + }, + + stopTimer: function(){ + clearTimeout(this.timer); + return this.removeEvent('complete', this.completeCheck); + } + +}); + + +/* +--- + +script: Color.js + +name: Color + +description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - Core/Number + - Core/Hash + - Core/Function + - MooTools.More + +provides: [Color] + +... +*/ + +(function(){ + +var Color = this.Color = new Type('Color', function(color, type){ + if (arguments.length >= 3){ + type = 'rgb'; color = Array.slice(arguments, 0, 3); + } else if (typeof color == 'string'){ + if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true); + else if (color.match(/hsb/)) color = color.hsbToRgb(); + else color = color.hexToRgb(true); + } + type = type || 'rgb'; + switch (type){ + case 'hsb': + var old = color; + color = color.hsbToRgb(); + color.hsb = old; + break; + case 'hex': color = color.hexToRgb(true); break; + } + color.rgb = color.slice(0, 3); + color.hsb = color.hsb || color.rgbToHsb(); + color.hex = color.rgbToHex(); + return Object.append(color, this); +}); + +Color.implement({ + + mix: function(){ + var colors = Array.slice(arguments); + var alpha = (typeOf(colors.getLast()) == 'number') ? colors.pop() : 50; + var rgb = this.slice(); + colors.each(function(color){ + color = new Color(color); + for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha)); + }); + return new Color(rgb, 'rgb'); + }, + + invert: function(){ + return new Color(this.map(function(value){ + return 255 - value; + })); + }, + + setHue: function(value){ + return new Color([value, this.hsb[1], this.hsb[2]], 'hsb'); + }, + + setSaturation: function(percent){ + return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb'); + }, + + setBrightness: function(percent){ + return new Color([this.hsb[0], this.hsb[1], percent], 'hsb'); + } + +}); + +this.$RGB = function(r, g, b){ + return new Color([r, g, b], 'rgb'); +}; + +this.$HSB = function(h, s, b){ + return new Color([h, s, b], 'hsb'); +}; + +this.$HEX = function(hex){ + return new Color(hex, 'hex'); +}; + +Array.implement({ + + rgbToHsb: function(){ + var red = this[0], + green = this[1], + blue = this[2], + hue = 0; + var max = Math.max(red, green, blue), + min = Math.min(red, green, blue); + var delta = max - min; + var brightness = max / 255, + saturation = (max != 0) ? delta / max : 0; + if (saturation != 0){ + var rr = (max - red) / delta; + var gr = (max - green) / delta; + var br = (max - blue) / delta; + if (red == max) hue = br - gr; + else if (green == max) hue = 2 + rr - br; + else hue = 4 + gr - rr; + hue /= 6; + if (hue < 0) hue++; + } + return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)]; + }, + + hsbToRgb: function(){ + var br = Math.round(this[2] / 100 * 255); + if (this[1] == 0){ + return [br, br, br]; + } else { + var hue = this[0] % 360; + var f = hue % 60; + var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255); + var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255); + var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255); + switch (Math.floor(hue / 60)){ + case 0: return [br, t, p]; + case 1: return [q, br, p]; + case 2: return [p, br, t]; + case 3: return [p, q, br]; + case 4: return [t, p, br]; + case 5: return [br, p, q]; + } + } + return false; + } + +}); + +String.implement({ + + rgbToHsb: function(){ + var rgb = this.match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHsb() : null; + }, + + hsbToRgb: function(){ + var hsb = this.match(/\d{1,3}/g); + return (hsb) ? hsb.hsbToRgb() : null; + } + +}); + +})(); + + diff --git a/module/webui/themes/default/js/static/mootools-more.min.js b/module/webui/themes/default/js/static/mootools-more.min.js new file mode 100644 index 000000000..ce03a60fd --- /dev/null +++ b/module/webui/themes/default/js/static/mootools-more.min.js @@ -0,0 +1,226 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/more/c1cc18c2fff04bcc58921b4dff80a6f1 + +packager build: + - packager build More/Form.Request More/Fx.Reveal More/Sortables More/Request.Periodical More/Color + +copyrights: + - [MooTools](http://mootools.net) + +licenses: + - [MIT License](http://mootools.net/license.txt) +... +*/ + +MooTools.More={version:"1.5.0",build:"73db5e24e6e9c5c87b3a27aebef2248053f7db37"};Class.Mutators.Binds=function(a){if(!this.prototype.initialize){this.implement("initialize",function(){}); +}return Array.from(a).concat(this.prototype.Binds||[]);};Class.Mutators.initialize=function(a){return function(){Array.from(this.Binds).each(function(b){var c=this[b]; +if(c){this[b]=c.bind(this);}},this);return a.apply(this,arguments);};};Class.Occlude=new Class({occlude:function(c,b){b=document.id(b||this.element);var a=b.retrieve(c||this.property); +if(a&&!this.occluded){return(this.occluded=a);}this.occluded=false;b.store(c||this.property,this);return this.occluded;}});Class.refactor=function(b,a){Object.each(a,function(e,d){var c=b.prototype[d]; +c=(c&&c.$origin)||c||function(){};b.implement(d,(typeof e=="function")?function(){var f=this.previous;this.previous=c;var g=e.apply(this,arguments);this.previous=f; +return g;}:e);});return b;};(function(){var b=function(e,d){var f=[];Object.each(d,function(g){Object.each(g,function(h){e.each(function(i){f.push(i+"-"+h+(i=="border"?"-width":"")); +});});});return f;};var c=function(f,e){var d=0;Object.each(e,function(h,g){if(g.test(f)){d=d+h.toInt();}});return d;};var a=function(d){return !!(!d||d.offsetHeight||d.offsetWidth); +};Element.implement({measure:function(h){if(a(this)){return h.call(this);}var g=this.getParent(),e=[];while(!a(g)&&g!=document.body){e.push(g.expose()); +g=g.getParent();}var f=this.expose(),d=h.call(this);f();e.each(function(i){i();});return d;},expose:function(){if(this.getStyle("display")!="none"){return function(){}; +}var d=this.style.cssText;this.setStyles({display:"block",position:"absolute",visibility:"hidden"});return function(){this.style.cssText=d;}.bind(this); +},getDimensions:function(d){d=Object.merge({computeSize:false},d);var i={x:0,y:0};var h=function(j,e){return(e.computeSize)?j.getComputedSize(e):j.getSize(); +};var f=this.getParent("body");if(f&&this.getStyle("display")=="none"){i=this.measure(function(){return h(this,d);});}else{if(f){try{i=h(this,d);}catch(g){}}}return Object.append(i,(i.x||i.x===0)?{width:i.x,height:i.y}:{x:i.width,y:i.height}); +},getComputedSize:function(d){d=Object.merge({styles:["padding","border"],planes:{height:["top","bottom"],width:["left","right"]},mode:"both"},d);var g={},e={width:0,height:0},f; +if(d.mode=="vertical"){delete e.width;delete d.planes.width;}else{if(d.mode=="horizontal"){delete e.height;delete d.planes.height;}}b(d.styles,d.planes).each(function(h){g[h]=this.getStyle(h).toInt(); +},this);Object.each(d.planes,function(i,h){var k=h.capitalize(),j=this.getStyle(h);if(j=="auto"&&!f){f=this.getDimensions();}j=g[h]=(j=="auto")?f[h]:j.toInt(); +e["total"+k]=j;i.each(function(m){var l=c(m,g);e["computed"+m.capitalize()]=l;e["total"+k]+=l;});},this);return Object.append(e,g);}});})();(function(b){var a=Element.Position={options:{relativeTo:document.body,position:{x:"center",y:"center"},offset:{x:0,y:0}},getOptions:function(d,c){c=Object.merge({},a.options,c); +a.setPositionOption(c);a.setEdgeOption(c);a.setOffsetOption(d,c);a.setDimensionsOption(d,c);return c;},setPositionOption:function(c){c.position=a.getCoordinateFromValue(c.position); +},setEdgeOption:function(d){var c=a.getCoordinateFromValue(d.edge);d.edge=c?c:(d.position.x=="center"&&d.position.y=="center")?{x:"center",y:"center"}:{x:"left",y:"top"}; +},setOffsetOption:function(f,d){var c={x:0,y:0};var e={x:0,y:0};var g=f.measure(function(){return document.id(this.getOffsetParent());});if(!g||g==f.getDocument().body){return; +}e=g.getScroll();c=g.measure(function(){var i=this.getPosition();if(this.getStyle("position")=="fixed"){var h=window.getScroll();i.x+=h.x;i.y+=h.y;}return i; +});d.offset={parentPositioned:g!=document.id(d.relativeTo),x:d.offset.x-c.x+e.x,y:d.offset.y-c.y+e.y};},setDimensionsOption:function(d,c){c.dimensions=d.getDimensions({computeSize:true,styles:["padding","border","margin"]}); +},getPosition:function(e,d){var c={};d=a.getOptions(e,d);var f=document.id(d.relativeTo)||document.body;a.setPositionCoordinates(d,c,f);if(d.edge){a.toEdge(c,d); +}var g=d.offset;c.left=((c.x>=0||g.parentPositioned||d.allowNegative)?c.x:0).toInt();c.top=((c.y>=0||g.parentPositioned||d.allowNegative)?c.y:0).toInt(); +a.toMinMax(c,d);if(d.relFixedPosition||f.getStyle("position")=="fixed"){a.toRelFixedPosition(f,c);}if(d.ignoreScroll){a.toIgnoreScroll(f,c);}if(d.ignoreMargins){a.toIgnoreMargins(c,d); +}c.left=Math.ceil(c.left);c.top=Math.ceil(c.top);delete c.x;delete c.y;return c;},setPositionCoordinates:function(k,g,d){var f=k.offset.y,h=k.offset.x,e=(d==document.body)?window.getScroll():d.getPosition(),j=e.y,c=e.x,i=window.getSize(); +switch(k.position.x){case"left":g.x=c+h;break;case"right":g.x=c+h+d.offsetWidth;break;default:g.x=c+((d==document.body?i.x:d.offsetWidth)/2)+h;break;}switch(k.position.y){case"top":g.y=j+f; +break;case"bottom":g.y=j+f+d.offsetHeight;break;default:g.y=j+((d==document.body?i.y:d.offsetHeight)/2)+f;break;}},toMinMax:function(c,d){var f={left:"x",top:"y"},e; +["minimum","maximum"].each(function(g){["left","top"].each(function(h){e=d[g]?d[g][f[h]]:null;if(e!=null&&((g=="minimum")?c[h]<e:c[h]>e)){c[h]=e;}});}); +},toRelFixedPosition:function(e,c){var d=window.getScroll();c.top+=d.y;c.left+=d.x;},toIgnoreScroll:function(e,d){var c=e.getScroll();d.top-=c.y;d.left-=c.x; +},toIgnoreMargins:function(c,d){c.left+=d.edge.x=="right"?d.dimensions["margin-right"]:(d.edge.x!="center"?-d.dimensions["margin-left"]:-d.dimensions["margin-left"]+((d.dimensions["margin-right"]+d.dimensions["margin-left"])/2)); +c.top+=d.edge.y=="bottom"?d.dimensions["margin-bottom"]:(d.edge.y!="center"?-d.dimensions["margin-top"]:-d.dimensions["margin-top"]+((d.dimensions["margin-bottom"]+d.dimensions["margin-top"])/2)); +},toEdge:function(c,d){var e={},g=d.dimensions,f=d.edge;switch(f.x){case"left":e.x=0;break;case"right":e.x=-g.x-g.computedRight-g.computedLeft;break;default:e.x=-(Math.round(g.totalWidth/2)); +break;}switch(f.y){case"top":e.y=0;break;case"bottom":e.y=-g.y-g.computedTop-g.computedBottom;break;default:e.y=-(Math.round(g.totalHeight/2));break;}c.x+=e.x; +c.y+=e.y;},getCoordinateFromValue:function(c){if(typeOf(c)!="string"){return c;}c=c.toLowerCase();return{x:c.test("left")?"left":(c.test("right")?"right":"center"),y:c.test(/upper|top/)?"top":(c.test("bottom")?"bottom":"center")}; +}};Element.implement({position:function(d){if(d&&(d.x!=null||d.y!=null)){return(b?b.apply(this,arguments):this);}var c=this.setStyle("position","absolute").calculatePosition(d); +return(d&&d.returnPos)?c:this.setStyles(c);},calculatePosition:function(c){return a.getPosition(this,c);}});})(Element.prototype.position);(function(){var a=false; +this.IframeShim=new Class({Implements:[Options,Events,Class.Occlude],options:{className:"iframeShim",src:'javascript:false;document.write("");',display:false,zIndex:null,margin:0,offset:{x:0,y:0},browsers:a},property:"IframeShim",initialize:function(c,b){this.element=document.id(c); +if(this.occlude()){return this.occluded;}this.setOptions(b);this.makeShim();return this;},makeShim:function(){if(this.options.browsers){var d=this.element.getStyle("zIndex").toInt(); +if(!d){d=1;var c=this.element.getStyle("position");if(c=="static"||!c){this.element.setStyle("position","relative");}this.element.setStyle("zIndex",d); +}d=((this.options.zIndex!=null||this.options.zIndex===0)&&d>this.options.zIndex)?this.options.zIndex:d-1;if(d<0){d=1;}this.shim=new Element("iframe",{src:this.options.src,scrolling:"no",frameborder:0,styles:{zIndex:d,position:"absolute",border:"none",filter:"progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"},"class":this.options.className}).store("IframeShim",this); +var b=(function(){this.shim.inject(this.element,"after");this[this.options.display?"show":"hide"]();this.fireEvent("inject");}).bind(this);if(!IframeShim.ready){window.addEvent("load",b); +}else{b();}}else{this.position=this.hide=this.show=this.dispose=Function.from(this);}},position:function(){if(!IframeShim.ready||!this.shim){return this; +}var b=this.element.measure(function(){return this.getSize();});if(this.options.margin!=undefined){b.x=b.x-(this.options.margin*2);b.y=b.y-(this.options.margin*2); +this.options.offset.x+=this.options.margin;this.options.offset.y+=this.options.margin;}this.shim.set({width:b.x,height:b.y}).position({relativeTo:this.element,offset:this.options.offset}); +return this;},hide:function(){if(this.shim){this.shim.setStyle("display","none");}return this;},show:function(){if(this.shim){this.shim.setStyle("display","block"); +}return this.position();},dispose:function(){if(this.shim){this.shim.dispose();}return this;},destroy:function(){if(this.shim){this.shim.destroy();}return this; +}});})();window.addEvent("load",function(){IframeShim.ready=true;});var Mask=new Class({Implements:[Options,Events],Binds:["position"],options:{style:{},"class":"mask",maskMargins:false,useIframeShim:true,iframeShimOptions:{}},initialize:function(b,a){this.target=document.id(b)||document.id(document.body); +this.target.store("mask",this);this.setOptions(a);this.render();this.inject();},render:function(){this.element=new Element("div",{"class":this.options["class"],id:this.options.id||"mask-"+String.uniqueID(),styles:Object.merge({},this.options.style,{display:"none"}),events:{click:function(a){this.fireEvent("click",a); +if(this.options.hideOnClick){this.hide();}}.bind(this)}});this.hidden=true;},toElement:function(){return this.element;},inject:function(b,a){a=a||(this.options.inject?this.options.inject.where:"")||(this.target==document.body?"inside":"after"); +b=b||(this.options.inject&&this.options.inject.target)||this.target;this.element.inject(b,a);if(this.options.useIframeShim){this.shim=new IframeShim(this.element,this.options.iframeShimOptions); +this.addEvents({show:this.shim.show.bind(this.shim),hide:this.shim.hide.bind(this.shim),destroy:this.shim.destroy.bind(this.shim)});}},position:function(){this.resize(this.options.width,this.options.height); +this.element.position({relativeTo:this.target,position:"topLeft",ignoreMargins:!this.options.maskMargins,ignoreScroll:this.target==document.body});return this; +},resize:function(a,e){var b={styles:["padding","border"]};if(this.options.maskMargins){b.styles.push("margin");}var d=this.target.getComputedSize(b);if(this.target==document.body){this.element.setStyles({width:0,height:0}); +var c=window.getScrollSize();if(d.totalHeight<c.y){d.totalHeight=c.y;}if(d.totalWidth<c.x){d.totalWidth=c.x;}}this.element.setStyles({width:Array.pick([a,d.totalWidth,d.x]),height:Array.pick([e,d.totalHeight,d.y])}); +return this;},show:function(){if(!this.hidden){return this;}window.addEvent("resize",this.position);this.position();this.showMask.apply(this,arguments); +return this;},showMask:function(){this.element.setStyle("display","block");this.hidden=false;this.fireEvent("show");},hide:function(){if(this.hidden){return this; +}window.removeEvent("resize",this.position);this.hideMask.apply(this,arguments);if(this.options.destroyOnHide){return this.destroy();}return this;},hideMask:function(){this.element.setStyle("display","none"); +this.hidden=true;this.fireEvent("hide");},toggle:function(){this[this.hidden?"show":"hide"]();},destroy:function(){this.hide();this.element.destroy();this.fireEvent("destroy"); +this.target.eliminate("mask");}});Element.Properties.mask={set:function(b){var a=this.retrieve("mask");if(a){a.destroy();}return this.eliminate("mask").store("mask:options",b); +},get:function(){var a=this.retrieve("mask");if(!a){a=new Mask(this,this.retrieve("mask:options"));this.store("mask",a);}return a;}};Element.implement({mask:function(a){if(a){this.set("mask",a); +}this.get("mask").show();return this;},unmask:function(){this.get("mask").hide();return this;}});var Spinner=new Class({Extends:Mask,Implements:Chain,options:{"class":"spinner",containerPosition:{},content:{"class":"spinner-content"},messageContainer:{"class":"spinner-msg"},img:{"class":"spinner-img"},fxOptions:{link:"chain"}},initialize:function(c,a){this.target=document.id(c)||document.id(document.body); +this.target.store("spinner",this);this.setOptions(a);this.render();this.inject();var b=function(){this.active=false;}.bind(this);this.addEvents({hide:b,show:b}); +},render:function(){this.parent();this.element.set("id",this.options.id||"spinner-"+String.uniqueID());this.content=document.id(this.options.content)||new Element("div",this.options.content); +this.content.inject(this.element);if(this.options.message){this.msg=document.id(this.options.message)||new Element("p",this.options.messageContainer).appendText(this.options.message); +this.msg.inject(this.content);}if(this.options.img){this.img=document.id(this.options.img)||new Element("div",this.options.img);this.img.inject(this.content); +}this.element.set("tween",this.options.fxOptions);},show:function(a){if(this.active){return this.chain(this.show.bind(this));}if(!this.hidden){this.callChain.delay(20,this); +return this;}this.target.set("aria-busy","true");this.active=true;return this.parent(a);},showMask:function(a){var b=function(){this.content.position(Object.merge({relativeTo:this.element},this.options.containerPosition)); +}.bind(this);if(a){this.parent();b();}else{if(!this.options.style.opacity){this.options.style.opacity=this.element.getStyle("opacity").toFloat();}this.element.setStyles({display:"block",opacity:0}).tween("opacity",this.options.style.opacity); +b();this.hidden=false;this.fireEvent("show");this.callChain();}},hide:function(a){if(this.active){return this.chain(this.hide.bind(this));}if(this.hidden){this.callChain.delay(20,this); +return this;}this.target.set("aria-busy","false");this.active=true;return this.parent(a);},hideMask:function(a){if(a){return this.parent();}this.element.tween("opacity",0).get("tween").chain(function(){this.element.setStyle("display","none"); +this.hidden=true;this.fireEvent("hide");this.callChain();}.bind(this));},destroy:function(){this.content.destroy();this.parent();this.target.eliminate("spinner"); +}});Request=Class.refactor(Request,{options:{useSpinner:false,spinnerOptions:{},spinnerTarget:false},initialize:function(a){this._send=this.send;this.send=function(b){var c=this.getSpinner(); +if(c){c.chain(this._send.pass(b,this)).show();}else{this._send(b);}return this;};this.previous(a);},getSpinner:function(){if(!this.spinner){var b=document.id(this.options.spinnerTarget)||document.id(this.options.update); +if(this.options.useSpinner&&b){b.set("spinner",this.options.spinnerOptions);var a=this.spinner=b.get("spinner");["complete","exception","cancel"].each(function(c){this.addEvent(c,a.hide.bind(a)); +},this);}}return this.spinner;}});Element.Properties.spinner={set:function(a){var b=this.retrieve("spinner");if(b){b.destroy();}return this.eliminate("spinner").store("spinner:options",a); +},get:function(){var a=this.retrieve("spinner");if(!a){a=new Spinner(this,this.retrieve("spinner:options"));this.store("spinner",a);}return a;}};Element.implement({spin:function(a){if(a){this.set("spinner",a); +}this.get("spinner").show();return this;},unspin:function(){this.get("spinner").hide();return this;}});String.implement({parseQueryString:function(d,a){if(d==null){d=true; +}if(a==null){a=true;}var c=this.split(/[&;]/),b={};if(!c.length){return b;}c.each(function(i){var e=i.indexOf("=")+1,g=e?i.substr(e):"",f=e?i.substr(0,e-1).match(/([^\]\[]+|(\B)(?=\]))/g):[i],h=b; +if(!f){return;}if(a){g=decodeURIComponent(g);}f.each(function(k,j){if(d){k=decodeURIComponent(k);}var l=h[k];if(j<f.length-1){h=h[k]=l||{};}else{if(typeOf(l)=="array"){l.push(g); +}else{h[k]=l!=null?[l,g]:g;}}});});return b;},cleanQueryString:function(a){return this.split("&").filter(function(e){var b=e.indexOf("="),c=b<0?"":e.substr(0,b),d=e.substr(b+1); +return a?a.call(null,c,d):(d||d===0);}).join("&");}});(function(){Events.Pseudos=function(h,e,f){var d="_monitorEvents:";var c=function(i){return{store:i.store?function(j,k){i.store(d+j,k); +}:function(j,k){(i._monitorEvents||(i._monitorEvents={}))[j]=k;},retrieve:i.retrieve?function(j,k){return i.retrieve(d+j,k);}:function(j,k){if(!i._monitorEvents){return k; +}return i._monitorEvents[j]||k;}};};var g=function(k){if(k.indexOf(":")==-1||!h){return null;}var j=Slick.parse(k).expressions[0][0],p=j.pseudos,i=p.length,o=[]; +while(i--){var n=p[i].key,m=h[n];if(m!=null){o.push({event:j.tag,value:p[i].value,pseudo:n,original:k,listener:m});}}return o.length?o:null;};return{addEvent:function(m,p,j){var n=g(m); +if(!n){return e.call(this,m,p,j);}var k=c(this),r=k.retrieve(m,[]),i=n[0].event,l=Array.slice(arguments,2),o=p,q=this;n.each(function(s){var t=s.listener,u=o; +if(t==false){i+=":"+s.pseudo+"("+s.value+")";}else{o=function(){t.call(q,s,u,arguments,o);};}});r.include({type:i,event:p,monitor:o});k.store(m,r);if(m!=i){e.apply(this,[m,p].concat(l)); +}return e.apply(this,[i,o].concat(l));},removeEvent:function(m,l){var k=g(m);if(!k){return f.call(this,m,l);}var n=c(this),j=n.retrieve(m);if(!j){return this; +}var i=Array.slice(arguments,2);f.apply(this,[m,l].concat(i));j.each(function(o,p){if(!l||o.event==l){f.apply(this,[o.type,o.monitor].concat(i));}delete j[p]; +},this);n.store(m,j);return this;}};};var b={once:function(e,f,d,c){f.apply(this,d);this.removeEvent(e.event,c).removeEvent(e.original,f);},throttle:function(d,e,c){if(!e._throttled){e.apply(this,c); +e._throttled=setTimeout(function(){e._throttled=false;},d.value||250);}},pause:function(d,e,c){clearTimeout(e._pause);e._pause=e.delay(d.value||250,this,c); +}};Events.definePseudo=function(c,d){b[c]=d;return this;};Events.lookupPseudo=function(c){return b[c];};var a=Events.prototype;Events.implement(Events.Pseudos(b,a.addEvent,a.removeEvent)); +["Request","Fx"].each(function(c){if(this[c]){this[c].implement(Events.prototype);}});})();(function(){var d={relay:false},c=["once","throttle","pause"],b=c.length; +while(b--){d[c[b]]=Events.lookupPseudo(c[b]);}DOMEvent.definePseudo=function(e,f){d[e]=f;return this;};var a=Element.prototype;[Element,Window,Document].invoke("implement",Events.Pseudos(d,a.addEvent,a.removeEvent)); +})();if(!window.Form){window.Form={};}(function(){Form.Request=new Class({Binds:["onSubmit","onFormValidate"],Implements:[Options,Events,Class.Occlude],options:{requestOptions:{evalScripts:true,useSpinner:true,emulation:false,link:"ignore"},sendButtonClicked:true,extraData:{},resetForm:true},property:"form.request",initialize:function(b,c,a){this.element=document.id(b); +if(this.occlude()){return this.occluded;}this.setOptions(a).setTarget(c).attach();},setTarget:function(a){this.target=document.id(a);if(!this.request){this.makeRequest(); +}else{this.request.setOptions({update:this.target});}return this;},toElement:function(){return this.element;},makeRequest:function(){var a=this;this.request=new Request.HTML(Object.merge({update:this.target,emulation:false,spinnerTarget:this.element,method:this.element.get("method")||"post"},this.options.requestOptions)).addEvents({success:function(c,e,d,b){["complete","success"].each(function(f){a.fireEvent(f,[a.target,c,e,d,b]); +});},failure:function(){a.fireEvent("complete",arguments).fireEvent("failure",arguments);},exception:function(){a.fireEvent("failure",arguments);}});return this.attachReset(); +},attachReset:function(){if(!this.options.resetForm){return this;}this.request.addEvent("success",function(){Function.attempt(function(){this.element.reset(); +}.bind(this));if(window.OverText){OverText.update();}}.bind(this));return this;},attach:function(a){var c=(a!=false)?"addEvent":"removeEvent";this.element[c]("click:relay(button, input[type=submit])",this.saveClickedButton.bind(this)); +var b=this.element.retrieve("validator");if(b){b[c]("onFormValidate",this.onFormValidate);}else{this.element[c]("submit",this.onSubmit);}return this;},detach:function(){return this.attach(false); +},enable:function(){return this.attach();},disable:function(){return this.detach();},onFormValidate:function(c,b,a){if(!a){return;}var d=this.element.retrieve("validator"); +if(c||(d&&!d.options.stopOnFailure)){a.stop();this.send();}},onSubmit:function(a){var b=this.element.retrieve("validator");if(b){this.element.removeEvent("submit",this.onSubmit); +b.addEvent("onFormValidate",this.onFormValidate);b.validate(a);return;}if(a){a.stop();}this.send();},saveClickedButton:function(b,c){var a=c.get("name"); +if(!a||!this.options.sendButtonClicked){return;}this.options.extraData[a]=c.get("value")||true;this.clickedCleaner=function(){delete this.options.extraData[a]; +this.clickedCleaner=function(){};}.bind(this);},clickedCleaner:function(){},send:function(){var b=this.element.toQueryString().trim(),a=Object.toQueryString(this.options.extraData); +if(b){b+="&"+a;}else{b=a;}this.fireEvent("send",[this.element,b.parseQueryString()]);this.request.send({data:b,url:this.options.requestOptions.url||this.element.get("action")}); +this.clickedCleaner();return this;}});Element.implement("formUpdate",function(c,b){var a=this.retrieve("form.request");if(!a){a=new Form.Request(this,c,b); +}else{if(c){a.setTarget(c);}if(b){a.setOptions(b).makeRequest();}}a.send();return this;});})();Element.implement({isDisplayed:function(){return this.getStyle("display")!="none"; +},isVisible:function(){var a=this.offsetWidth,b=this.offsetHeight;return(a==0&&b==0)?false:(a>0&&b>0)?true:this.style.display!="none";},toggle:function(){return this[this.isDisplayed()?"hide":"show"](); +},hide:function(){var b;try{b=this.getStyle("display");}catch(a){}if(b=="none"){return this;}return this.store("element:_originalDisplay",b||"").setStyle("display","none"); +},show:function(a){if(!a&&this.isDisplayed()){return this;}a=a||this.retrieve("element:_originalDisplay")||"block";return this.setStyle("display",(a=="none")?"block":a); +},swapClass:function(a,b){return this.removeClass(a).addClass(b);}});Document.implement({clearSelection:function(){if(window.getSelection){var a=window.getSelection(); +if(a&&a.removeAllRanges){a.removeAllRanges();}}else{if(document.selection&&document.selection.empty){try{document.selection.empty();}catch(b){}}}}});(function(){var a=function(d){var b=d.options.hideInputs; +if(window.OverText){var c=[null];OverText.each(function(e){c.include("."+e.options.labelClass);});if(c){b+=c.join(", ");}}return(b)?d.element.getElements(b):null; +};Fx.Reveal=new Class({Extends:Fx.Morph,options:{link:"cancel",styles:["padding","border","margin"],transitionOpacity:"opacity" in document.documentElement,mode:"vertical",display:function(){return this.element.get("tag")!="tr"?"block":"table-row"; +},opacity:1,hideInputs:!("opacity" in document.documentElement)?"select, input, textarea, object, embed":null},dissolve:function(){if(!this.hiding&&!this.showing){if(this.element.getStyle("display")!="none"){this.hiding=true; +this.showing=false;this.hidden=true;this.cssText=this.element.style.cssText;var d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode}); +if(this.options.transitionOpacity){d.opacity=this.options.opacity;}var c={};Object.each(d,function(f,e){c[e]=[f,0];});this.element.setStyles({display:Function.from(this.options.display).call(this),overflow:"hidden"}); +var b=a(this);if(b){b.setStyle("visibility","hidden");}this.$chain.unshift(function(){if(this.hidden){this.hiding=false;this.element.style.cssText=this.cssText; +this.element.setStyle("display","none");if(b){b.setStyle("visibility","visible");}}this.fireEvent("hide",this.element);this.callChain();}.bind(this));this.start(c); +}else{this.callChain.delay(10,this);this.fireEvent("complete",this.element);this.fireEvent("hide",this.element);}}else{if(this.options.link=="chain"){this.chain(this.dissolve.bind(this)); +}else{if(this.options.link=="cancel"&&!this.hiding){this.cancel();this.dissolve();}}}return this;},reveal:function(){if(!this.showing&&!this.hiding){if(this.element.getStyle("display")=="none"){this.hiding=false; +this.showing=true;this.hidden=false;this.cssText=this.element.style.cssText;var d;this.element.measure(function(){d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode}); +}.bind(this));if(this.options.heightOverride!=null){d.height=this.options.heightOverride.toInt();}if(this.options.widthOverride!=null){d.width=this.options.widthOverride.toInt(); +}if(this.options.transitionOpacity){this.element.setStyle("opacity",0);d.opacity=this.options.opacity;}var c={height:0,display:Function.from(this.options.display).call(this)}; +Object.each(d,function(f,e){c[e]=0;});c.overflow="hidden";this.element.setStyles(c);var b=a(this);if(b){b.setStyle("visibility","hidden");}this.$chain.unshift(function(){this.element.style.cssText=this.cssText; +this.element.setStyle("display",Function.from(this.options.display).call(this));if(!this.hidden){this.showing=false;}if(b){b.setStyle("visibility","visible"); +}this.callChain();this.fireEvent("show",this.element);}.bind(this));this.start(d);}else{this.callChain();this.fireEvent("complete",this.element);this.fireEvent("show",this.element); +}}else{if(this.options.link=="chain"){this.chain(this.reveal.bind(this));}else{if(this.options.link=="cancel"&&!this.showing){this.cancel();this.reveal(); +}}}return this;},toggle:function(){if(this.element.getStyle("display")=="none"){this.reveal();}else{this.dissolve();}return this;},cancel:function(){this.parent.apply(this,arguments); +if(this.cssText!=null){this.element.style.cssText=this.cssText;}this.hiding=false;this.showing=false;return this;}});Element.Properties.reveal={set:function(b){this.get("reveal").cancel().setOptions(b); +return this;},get:function(){var b=this.retrieve("reveal");if(!b){b=new Fx.Reveal(this);this.store("reveal",b);}return b;}};Element.Properties.dissolve=Element.Properties.reveal; +Element.implement({reveal:function(b){this.get("reveal").setOptions(b).reveal();return this;},dissolve:function(b){this.get("reveal").setOptions(b).dissolve(); +return this;},nix:function(b){var c=Array.link(arguments,{destroy:Type.isBoolean,options:Type.isObject});this.get("reveal").setOptions(b).dissolve().chain(function(){this[c.destroy?"destroy":"dispose"](); +}.bind(this));return this;},wink:function(){var c=Array.link(arguments,{duration:Type.isNumber,options:Type.isObject});var b=this.get("reveal").setOptions(c.options); +b.reveal().chain(function(){(function(){b.dissolve();}).delay(c.duration||2000);});}});})();var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var b=Array.link(arguments,{options:Type.isObject,element:function(c){return c!=null; +}});this.element=document.id(b.element);this.document=this.element.getDocument();this.setOptions(b.options||{});var a=typeOf(this.options.handle);this.handles=((a=="array"||a=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element; +this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection="selectstart" in document?"selectstart":"mousedown";if("ondragstart" in document&&!("FileReader" in window)&&!Drag.ondragstartFixed){document.ondragstart=Function.from(false); +Drag.ondragstartFixed=true;}this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:Function.from(false)}; +this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start); +return this;},start:function(a){var j=this.options;if(a.rightClick){return;}if(j.preventDefault){a.preventDefault();}if(j.stopPropagation){a.stopPropagation(); +}this.mouse.start=a.page;this.fireEvent("beforeStart",this.element);var c=j.limit;this.limit={x:[],y:[]};var e,g;for(e in j.modifiers){if(!j.modifiers[e]){continue; +}var b=this.element.getStyle(j.modifiers[e]);if(b&&!b.match(/px$/)){if(!g){g=this.element.getCoordinates(this.element.getOffsetParent());}b=g[j.modifiers[e]]; +}if(j.style){this.value.now[e]=(b||0).toInt();}else{this.value.now[e]=this.element[j.modifiers[e]];}if(j.invert){this.value.now[e]*=-1;}this.mouse.pos[e]=a.page[e]-this.value.now[e]; +if(c&&c[e]){var d=2;while(d--){var f=c[e][d];if(f||f===0){this.limit[e][d]=(typeof f=="function")?f():f;}}}}if(typeOf(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}; +}var h={mousemove:this.bound.check,mouseup:this.bound.cancel};h[this.selection]=this.bound.eventStop;this.document.addEvents(h);},check:function(a){if(this.options.preventDefault){a.preventDefault(); +}var b=Math.round(Math.sqrt(Math.pow(a.page.x-this.mouse.start.x,2)+Math.pow(a.page.y-this.mouse.start.y,2)));if(b>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop}); +this.fireEvent("start",[this.element,a]).fireEvent("snap",this.element);}},drag:function(b){var a=this.options;if(a.preventDefault){b.preventDefault(); +}this.mouse.now=b.page;for(var c in a.modifiers){if(!a.modifiers[c]){continue;}this.value.now[c]=this.mouse.now[c]-this.mouse.pos[c];if(a.invert){this.value.now[c]*=-1; +}if(a.limit&&this.limit[c]){if((this.limit[c][1]||this.limit[c][1]===0)&&(this.value.now[c]>this.limit[c][1])){this.value.now[c]=this.limit[c][1];}else{if((this.limit[c][0]||this.limit[c][0]===0)&&(this.value.now[c]<this.limit[c][0])){this.value.now[c]=this.limit[c][0]; +}}}if(a.grid[c]){this.value.now[c]-=((this.value.now[c]-(this.limit[c][0]||0))%a.grid[c]);}if(a.style){this.element.setStyle(a.modifiers[c],this.value.now[c]+a.unit); +}else{this.element[a.modifiers[c]]=this.value.now[c];}}this.fireEvent("drag",[this.element,b]);},cancel:function(a){this.document.removeEvents({mousemove:this.bound.check,mouseup:this.bound.cancel}); +if(a){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element);}},stop:function(b){var a={mousemove:this.bound.drag,mouseup:this.bound.stop}; +a[this.selection]=this.bound.eventStop;this.document.removeEvents(a);if(b){this.fireEvent("complete",[this.element,b]);}}});Element.implement({makeResizable:function(a){var b=new Drag(this,Object.merge({modifiers:{x:"width",y:"height"}},a)); +this.store("resizer",b);return b.addEvent("drag",function(){this.fireEvent("resize",b);}.bind(this));}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false,precalculate:false,includeMargins:true,checkDroppables:true},initialize:function(b,a){this.parent(b,a); +b=this.element;this.droppables=$$(this.options.droppables);this.setContainer(this.options.container);if(this.options.style){if(this.options.modifiers.x=="left"&&this.options.modifiers.y=="top"){var c=b.getOffsetParent(),d=b.getStyles("left","top"); +if(c&&(d.left=="auto"||d.top=="auto")){b.setPosition(b.getPosition(c));}}if(b.getStyle("position")=="static"){b.setStyle("position","absolute");}}this.addEvent("start",this.checkDroppables,true); +this.overed=null;},setContainer:function(a){this.container=document.id(a);if(this.container&&typeOf(this.container)!="element"){this.container=document.id(this.container.getDocument().body); +}},start:function(a){if(this.container){this.options.limit=this.calculateLimit();}if(this.options.precalculate){this.positions=this.droppables.map(function(b){return b.getCoordinates(); +});}this.parent(a);},calculateLimit:function(){var j=this.element,e=this.container,d=document.id(j.getOffsetParent())||document.body,h=e.getCoordinates(d),c={},b={},k={},g={},m={}; +["top","right","bottom","left"].each(function(q){c[q]=j.getStyle("margin-"+q).toInt();b[q]=j.getStyle("border-"+q).toInt();k[q]=e.getStyle("margin-"+q).toInt(); +g[q]=e.getStyle("border-"+q).toInt();m[q]=d.getStyle("padding-"+q).toInt();},this);var f=j.offsetWidth+c.left+c.right,p=j.offsetHeight+c.top+c.bottom,i=0,l=0,o=h.right-g.right-f,a=h.bottom-g.bottom-p; +if(this.options.includeMargins){i+=c.left;l+=c.top;}else{o+=c.right;a+=c.bottom;}if(j.getStyle("position")=="relative"){var n=j.getCoordinates(d);n.left-=j.getStyle("left").toInt(); +n.top-=j.getStyle("top").toInt();i-=n.left;l-=n.top;if(e.getStyle("position")!="relative"){i+=g.left;l+=g.top;}o+=c.left-n.left;a+=c.top-n.top;if(e!=d){i+=k.left+m.left; +if(!m.left&&i<0){i=0;}l+=d==document.body?0:k.top+m.top;if(!m.top&&l<0){l=0;}}}else{i-=c.left;l-=c.top;if(e!=d){i+=h.left+g.left;l+=h.top+g.top;}}return{x:[i,o],y:[l,a]}; +},getDroppableCoordinates:function(c){var b=c.getCoordinates();if(c.getStyle("position")=="fixed"){var a=window.getScroll();b.left+=a.x;b.right+=a.x;b.top+=a.y; +b.bottom+=a.y;}return b;},checkDroppables:function(){var a=this.droppables.filter(function(d,c){d=this.positions?this.positions[c]:this.getDroppableCoordinates(d); +var b=this.mouse.now;return(b.x>d.left&&b.x<d.right&&b.y<d.bottom&&b.y>d.top);},this).getLast();if(this.overed!=a){if(this.overed){this.fireEvent("leave",[this.element,this.overed]); +}if(a){this.fireEvent("enter",[this.element,a]);}this.overed=a;}},drag:function(a){this.parent(a);if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables(); +}},stop:function(a){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,a]);this.overed=null;return this.parent(a);}});Element.implement({makeDraggable:function(a){var b=new Drag.Move(this,a); +this.store("dragger",b);return b;}});var Sortables=new Class({Implements:[Events,Options],options:{opacity:1,clone:false,revert:false,handle:false,dragOptions:{},unDraggableTags:["button","input","a","textarea","select","option"]},initialize:function(a,b){this.setOptions(b); +this.elements=[];this.lists=[];this.idle=true;this.addLists($$(document.id(a)||a));if(!this.options.clone){this.options.revert=false;}if(this.options.revert){this.effect=new Fx.Morph(null,Object.merge({duration:250,link:"cancel"},this.options.revert)); +}},attach:function(){this.addLists(this.lists);return this;},detach:function(){this.lists=this.removeLists(this.lists);return this;},addItems:function(){Array.flatten(arguments).each(function(a){this.elements.push(a); +var b=a.retrieve("sortables:start",function(c){this.start.call(this,c,a);}.bind(this));(this.options.handle?a.getElement(this.options.handle)||a:a).addEvent("mousedown",b); +},this);return this;},addLists:function(){Array.flatten(arguments).each(function(a){this.lists.include(a);this.addItems(a.getChildren());},this);return this; +},removeItems:function(){return $$(Array.flatten(arguments).map(function(a){this.elements.erase(a);var b=a.retrieve("sortables:start");(this.options.handle?a.getElement(this.options.handle)||a:a).removeEvent("mousedown",b); +return a;},this));},removeLists:function(){return $$(Array.flatten(arguments).map(function(a){this.lists.erase(a);this.removeItems(a.getChildren());return a; +},this));},getDroppableCoordinates:function(c){var d=c.getOffsetParent();var b=c.getPosition(d);var a={w:window.getScroll(),offsetParent:d.getScroll()}; +b.x+=a.offsetParent.x;b.y+=a.offsetParent.y;if(d.getStyle("position")=="fixed"){b.x-=a.w.x;b.y-=a.w.y;}return b;},getClone:function(b,a){if(!this.options.clone){return new Element(a.tagName).inject(document.body); +}if(typeOf(this.options.clone)=="function"){return this.options.clone.call(this,b,a,this.list);}var c=a.clone(true).setStyles({margin:0,position:"absolute",visibility:"hidden",width:a.getStyle("width")}).addEvent("mousedown",function(d){a.fireEvent("mousedown",d); +});if(c.get("html").test("radio")){c.getElements("input[type=radio]").each(function(d,e){d.set("name","clone_"+e);if(d.get("checked")){a.getElements("input[type=radio]")[e].set("checked",true); +}});}return c.inject(this.list).setPosition(this.getDroppableCoordinates(this.element));},getDroppables:function(){var a=this.list.getChildren().erase(this.clone).erase(this.element); +if(!this.options.constrain){a.append(this.lists).erase(this.list);}return a;},insert:function(c,b){var a="inside";if(this.lists.contains(b)){this.list=b; +this.drag.droppables=this.getDroppables();}else{a=this.element.getAllPrevious().contains(b)?"before":"after";}this.element.inject(b,a);this.fireEvent("sort",[this.element,this.clone]); +},start:function(b,a){if(!this.idle||b.rightClick||(!this.options.handle&&this.options.unDraggableTags.contains(b.target.get("tag")))){return;}this.idle=false; +this.element=a;this.opacity=a.getStyle("opacity");this.list=a.getParent();this.clone=this.getClone(b,a);this.drag=new Drag.Move(this.clone,Object.merge({droppables:this.getDroppables()},this.options.dragOptions)).addEvents({onSnap:function(){b.stop(); +this.clone.setStyle("visibility","visible");this.element.setStyle("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone]); +}.bind(this),onEnter:this.insert.bind(this),onCancel:this.end.bind(this),onComplete:this.end.bind(this)});this.clone.inject(this.element,"before");this.drag.start(b); +},end:function(){this.drag.detach();this.element.setStyle("opacity",this.opacity);var a=this;if(this.effect){var c=this.element.getStyles("width","height"),e=this.clone,d=e.computePosition(this.getDroppableCoordinates(e)); +var b=function(){this.removeEvent("cancel",b);e.destroy();a.reset();};this.effect.element=e;this.effect.start({top:d.top,left:d.left,width:c.width,height:c.height,opacity:0.25}).addEvent("cancel",b).chain(b); +}else{this.clone.destroy();a.reset();}},reset:function(){this.idle=true;this.fireEvent("complete",this.element);},serialize:function(){var c=Array.link(arguments,{modifier:Type.isFunction,index:function(d){return d!=null; +}});var b=this.lists.map(function(d){return d.getChildren().map(c.modifier||function(e){return e.get("id");},this);},this);var a=c.index;if(this.lists.length==1){a=0; +}return(a||a===0)&&a>=0&&a<this.lists.length?b[a]:b;}});Request.implement({options:{initialDelay:5000,delay:5000,limit:60000},startTimer:function(b){var a=function(){if(!this.running){this.send({data:b}); +}};this.lastDelay=this.options.initialDelay;this.timer=a.delay(this.lastDelay,this);this.completeCheck=function(c){clearTimeout(this.timer);this.lastDelay=(c)?this.options.delay:(this.lastDelay+this.options.delay).min(this.options.limit); +this.timer=a.delay(this.lastDelay,this);};return this.addEvent("complete",this.completeCheck);},stopTimer:function(){clearTimeout(this.timer);return this.removeEvent("complete",this.completeCheck); +}});(function(){var a=this.Color=new Type("Color",function(c,d){if(arguments.length>=3){d="rgb";c=Array.slice(arguments,0,3);}else{if(typeof c=="string"){if(c.match(/rgb/)){c=c.rgbToHex().hexToRgb(true); +}else{if(c.match(/hsb/)){c=c.hsbToRgb();}else{c=c.hexToRgb(true);}}}}d=d||"rgb";switch(d){case"hsb":var b=c;c=c.hsbToRgb();c.hsb=b;break;case"hex":c=c.hexToRgb(true); +break;}c.rgb=c.slice(0,3);c.hsb=c.hsb||c.rgbToHsb();c.hex=c.rgbToHex();return Object.append(c,this);});a.implement({mix:function(){var b=Array.slice(arguments); +var d=(typeOf(b.getLast())=="number")?b.pop():50;var c=this.slice();b.each(function(e){e=new a(e);for(var f=0;f<3;f++){c[f]=Math.round((c[f]/100*(100-d))+(e[f]/100*d)); +}});return new a(c,"rgb");},invert:function(){return new a(this.map(function(b){return 255-b;}));},setHue:function(b){return new a([b,this.hsb[1],this.hsb[2]],"hsb"); +},setSaturation:function(b){return new a([this.hsb[0],b,this.hsb[2]],"hsb");},setBrightness:function(b){return new a([this.hsb[0],this.hsb[1],b],"hsb"); +}});this.$RGB=function(e,d,c){return new a([e,d,c],"rgb");};this.$HSB=function(e,d,c){return new a([e,d,c],"hsb");};this.$HEX=function(b){return new a(b,"hex"); +};Array.implement({rgbToHsb:function(){var c=this[0],d=this[1],k=this[2],h=0;var j=Math.max(c,d,k),f=Math.min(c,d,k);var l=j-f;var i=j/255,g=(j!=0)?l/j:0; +if(g!=0){var e=(j-c)/l;var b=(j-d)/l;var m=(j-k)/l;if(c==j){h=m-b;}else{if(d==j){h=2+e-m;}else{h=4+b-e;}}h/=6;if(h<0){h++;}}return[Math.round(h*360),Math.round(g*100),Math.round(i*100)]; +},hsbToRgb:function(){var d=Math.round(this[2]/100*255);if(this[1]==0){return[d,d,d];}else{var b=this[0]%360;var g=b%60;var h=Math.round((this[2]*(100-this[1]))/10000*255); +var e=Math.round((this[2]*(6000-this[1]*g))/600000*255);var c=Math.round((this[2]*(6000-this[1]*(60-g)))/600000*255);switch(Math.floor(b/60)){case 0:return[d,c,h]; +case 1:return[e,d,h];case 2:return[h,d,c];case 3:return[h,e,d];case 4:return[c,h,d];case 5:return[d,h,e];}}return false;}});String.implement({rgbToHsb:function(){var b=this.match(/\d{1,3}/g); +return(b)?b.rgbToHsb():null;},hsbToRgb:function(){var b=this.match(/\d{1,3}/g);return(b)?b.hsbToRgb():null;}});})();
\ No newline at end of file diff --git a/module/webui/themes/default/js/static/purr.js b/module/webui/themes/default/js/static/purr.js new file mode 100644 index 000000000..9cbc503d9 --- /dev/null +++ b/module/webui/themes/default/js/static/purr.js @@ -0,0 +1,309 @@ +/* +--- +script: purr.js + +description: Class to create growl-style popup notifications. + +license: MIT-style + +authors: [atom smith] + +requires: +- core/1.3: [Core, Browser, Array, Function, Number, String, Hash, Event, Class.Extras, Element.Event, Element.Style, Element.Dimensions, Fx.CSS, FX.Tween, Fx.Morph] + +provides: [Purr, Element.alert] +... +*/ + + +var Purr = new Class({ + + 'options': { + 'mode': 'top', + 'position': 'left', + 'elementAlertClass': 'purr-element-alert', + 'elements': { + 'wrapper': 'div', + 'alert': 'div', + 'buttonWrapper': 'div', + 'button': 'button' + }, + 'elementOptions': { + 'wrapper': { + 'styles': { + 'position': 'fixed', + 'z-index': '9999' + }, + 'class': 'purr-wrapper' + }, + 'alert': { + 'class': 'purr-alert', + 'styles': { + 'opacity': '.85' + } + }, + 'buttonWrapper': { + 'class': 'purr-button-wrapper' + }, + 'button': { + 'class': 'purr-button' + } + }, + 'alert': { + 'buttons': [], + 'clickDismiss': true, + 'hoverWait': true, + 'hideAfter': 5000, + 'fx': { + 'duration': 500 + }, + 'highlight': false, + 'highlightRepeat': false, + 'highlight': { + 'start': '#FF0', + 'end': false + } + } + }, + + 'Implements': [Options, Events, Chain], + + 'initialize': function(options){ + this.setOptions(options); + this.createWrapper(); + return this; + }, + + 'bindAlert': function(){ + return this.alert.bind(this); + }, + + 'createWrapper': function(){ + this.wrapper = new Element(this.options.elements.wrapper, this.options.elementOptions.wrapper); + if(this.options.mode == 'top') + { + this.wrapper.setStyle('top', 0); + } + else + { + this.wrapper.setStyle('bottom', 0); + } + document.id(document.body).grab(this.wrapper); + this.positionWrapper(this.options.position); + }, + + 'positionWrapper': function(position){ + if(typeOf(position) == 'object') + { + + var wrapperCoords = this.getWrapperCoords(); + + this.wrapper.setStyles({ + 'bottom': '', + 'left': position.x, + 'top': position.y - wrapperCoords.height, + 'position': 'absolute' + }); + } + else if(position == 'left') + { + this.wrapper.setStyle('left', 0); + } + else if(position == 'right') + { + this.wrapper.setStyle('right', 0); + } + else + { + this.wrapper.setStyle('left', (window.innerWidth / 2) - (this.getWrapperCoords().width / 2)); + } + return this; + }, + + 'getWrapperCoords': function(){ + this.wrapper.setStyle('visibility', 'hidden'); + var measurer = this.alert('need something in here to measure'); + var coords = this.wrapper.getCoordinates(); + measurer.destroy(); + this.wrapper.setStyle('visibility',''); + return coords; + }, + + 'alert': function(msg, options){ + + options = Object.merge({}, this.options.alert, options || {}); + + var alert = new Element(this.options.elements.alert, this.options.elementOptions.alert); + + if(typeOf(msg) == 'string') + { + alert.set('html', msg); + } + else if(typeOf(msg) == 'element') + { + alert.grab(msg); + } + else if(typeOf(msg) == 'array') + { + var alerts = []; + msg.each(function(m){ + alerts.push(this.alert(m, options)); + }, this); + return alerts; + } + + alert.store('options', options); + + if(options.buttons.length > 0) + { + options.clickDismiss = false; + options.hideAfter = false; + options.hoverWait = false; + var buttonWrapper = new Element(this.options.elements.buttonWrapper, this.options.elementOptions.buttonWrapper); + alert.grab(buttonWrapper); + options.buttons.each(function(button){ + if(button.text != undefined) + { + var callbackButton = new Element(this.options.elements.button, this.options.elementOptions.button); + callbackButton.set('html', button.text); + if(button.callback != undefined) + { + callbackButton.addEvent('click', button.callback.pass(alert)); + } + if(button.dismiss != undefined && button.dismiss) + { + callbackButton.addEvent('click', this.dismiss.pass(alert, this)); + } + buttonWrapper.grab(callbackButton); + } + }, this); + } + if(options.className != undefined) + { + alert.addClass(options.className); + } + + this.wrapper.grab(alert, (this.options.mode == 'top') ? 'bottom' : 'top'); + + var fx = Object.merge(this.options.alert.fx, options.fx); + var alertFx = new Fx.Morph(alert, fx); + alert.store('fx', alertFx); + this.fadeIn(alert); + + if(options.highlight) + { + alertFx.addEvent('complete', function(){ + alert.highlight(options.highlight.start, options.highlight.end); + if(options.highlightRepeat) + { + alert.highlight.periodical(options.highlightRepeat, alert, [options.highlight.start, options.highlight.end]); + } + }); + } + if(options.hideAfter) + { + this.dismiss(alert); + } + + if(options.clickDismiss) + { + alert.addEvent('click', function(){ + this.holdUp = false; + this.dismiss(alert, true); + }.bind(this)); + } + + if(options.hoverWait) + { + alert.addEvents({ + 'mouseenter': function(){ + this.holdUp = true; + }.bind(this), + 'mouseleave': function(){ + this.holdUp = false; + }.bind(this) + }); + } + + return alert; + }, + + 'fadeIn': function(alert){ + var alertFx = alert.retrieve('fx'); + alertFx.set({ + 'opacity': 0 + }); + alertFx.start({ + 'opacity': [this.options.elementOptions.alert.styles.opacity, .9].pick(), + }); + }, + + 'dismiss': function(alert, now){ + now = now || false; + var options = alert.retrieve('options'); + if(now) + { + this.fadeOut(alert); + } + else + { + this.fadeOut.delay(options.hideAfter, this, alert); + } + }, + + 'fadeOut': function(alert){ + if(this.holdUp) + { + this.dismiss.delay(100, this, [alert, true]) + return null; + } + var alertFx = alert.retrieve('fx'); + if(!alertFx) + { + return null; + } + var to = { + 'opacity': 0 + } + if(this.options.mode == 'top') + { + to['margin-top'] = '-'+alert.offsetHeight+'px'; + } + else + { + to['margin-bottom'] = '-'+alert.offsetHeight+'px'; + } + alertFx.start(to); + alertFx.addEvent('complete', function(){ + alert.destroy(); + }); + } +}); + +Element.implement({ + + 'alert': function(msg, options){ + var alert = this.retrieve('alert'); + if(!alert) + { + options = options || { + 'mode':'top' + }; + alert = new Purr(options) + this.store('alert', alert); + } + + var coords = this.getCoordinates(); + + alert.alert(msg, options); + + alert.wrapper.setStyles({ + 'bottom': '', + 'left': (coords.left - (alert.wrapper.getWidth() / 2)) + (this.getWidth() / 2), + 'top': coords.top - (alert.wrapper.getHeight()), + 'position': 'absolute' + }); + + } + +});
\ No newline at end of file diff --git a/module/webui/themes/default/js/static/purr.min.js b/module/webui/themes/default/js/static/purr.min.js new file mode 100644 index 000000000..bf70e357d --- /dev/null +++ b/module/webui/themes/default/js/static/purr.min.js @@ -0,0 +1 @@ +var Purr=new Class({options:{mode:"top",position:"left",elementAlertClass:"purr-element-alert",elements:{wrapper:"div",alert:"div",buttonWrapper:"div",button:"button"},elementOptions:{wrapper:{styles:{position:"fixed","z-index":"9999"},"class":"purr-wrapper"},alert:{"class":"purr-alert",styles:{opacity:".85"}},buttonWrapper:{"class":"purr-button-wrapper"},button:{"class":"purr-button"}},alert:{buttons:[],clickDismiss:!0,hoverWait:!0,hideAfter:5e3,fx:{duration:500},highlight:!1,highlightRepeat:!1,highlight:{start:"#FF0",end:!1}}},Implements:[Options,Events,Chain],initialize:function(t){return this.setOptions(t),this.createWrapper(),this},bindAlert:function(){return this.alert.bind(this)},createWrapper:function(){this.wrapper=new Element(this.options.elements.wrapper,this.options.elementOptions.wrapper),"top"==this.options.mode?this.wrapper.setStyle("top",0):this.wrapper.setStyle("bottom",0),document.id(document.body).grab(this.wrapper),this.positionWrapper(this.options.position)},positionWrapper:function(t){if("object"==typeOf(t)){var e=this.getWrapperCoords();this.wrapper.setStyles({bottom:"",left:t.x,top:t.y-e.height,position:"absolute"})}else"left"==t?this.wrapper.setStyle("left",0):"right"==t?this.wrapper.setStyle("right",0):this.wrapper.setStyle("left",window.innerWidth/2-this.getWrapperCoords().width/2);return this},getWrapperCoords:function(){this.wrapper.setStyle("visibility","hidden");var t=this.alert("need something in here to measure"),e=this.wrapper.getCoordinates();return t.destroy(),this.wrapper.setStyle("visibility",""),e},alert:function(t,e){e=Object.merge({},this.options.alert,e||{});var i=new Element(this.options.elements.alert,this.options.elementOptions.alert);if("string"==typeOf(t))i.set("html",t);else if("element"==typeOf(t))i.grab(t);else if("array"==typeOf(t)){var s=[];return t.each(function(t){s.push(this.alert(t,e))},this),s}if(i.store("options",e),e.buttons.length>0){e.clickDismiss=!1,e.hideAfter=!1,e.hoverWait=!1;var r=new Element(this.options.elements.buttonWrapper,this.options.elementOptions.buttonWrapper);i.grab(r),e.buttons.each(function(t){if(void 0!=t.text){var e=new Element(this.options.elements.button,this.options.elementOptions.button);e.set("html",t.text),void 0!=t.callback&&e.addEvent("click",t.callback.pass(i)),void 0!=t.dismiss&&t.dismiss&&e.addEvent("click",this.dismiss.pass(i,this)),r.grab(e)}},this)}void 0!=e.className&&i.addClass(e.className),this.wrapper.grab(i,"top"==this.options.mode?"bottom":"top");var o=Object.merge(this.options.alert.fx,e.fx),n=new Fx.Morph(i,o);return i.store("fx",n),this.fadeIn(i),e.highlight&&n.addEvent("complete",function(){i.highlight(e.highlight.start,e.highlight.end),e.highlightRepeat&&i.highlight.periodical(e.highlightRepeat,i,[e.highlight.start,e.highlight.end])}),e.hideAfter&&this.dismiss(i),e.clickDismiss&&i.addEvent("click",function(){this.holdUp=!1,this.dismiss(i,!0)}.bind(this)),e.hoverWait&&i.addEvents({mouseenter:function(){this.holdUp=!0}.bind(this),mouseleave:function(){this.holdUp=!1}.bind(this)}),i},fadeIn:function(t){var e=t.retrieve("fx");e.set({opacity:0}),e.start({opacity:[this.options.elementOptions.alert.styles.opacity,.9].pick()})},dismiss:function(t,e){e=e||!1;var i=t.retrieve("options");e?this.fadeOut(t):this.fadeOut.delay(i.hideAfter,this,t)},fadeOut:function(t){if(this.holdUp)return this.dismiss.delay(100,this,[t,!0]),null;var e=t.retrieve("fx");if(!e)return null;var i={opacity:0};"top"==this.options.mode?i["margin-top"]="-"+t.offsetHeight+"px":i["margin-bottom"]="-"+t.offsetHeight+"px",e.start(i),e.addEvent("complete",function(){t.destroy()})}});Element.implement({alert:function(t,e){var i=this.retrieve("alert");i||(e=e||{mode:"top"},i=new Purr(e),this.store("alert",i));var s=this.getCoordinates();i.alert(t,e),i.wrapper.setStyles({bottom:"",left:s.left-i.wrapper.getWidth()/2+this.getWidth()/2,top:s.top-i.wrapper.getHeight(),position:"absolute"})}});
\ No newline at end of file diff --git a/module/webui/themes/default/js/static/tinytab.js b/module/webui/themes/default/js/static/tinytab.js new file mode 100644 index 000000000..de50279fc --- /dev/null +++ b/module/webui/themes/default/js/static/tinytab.js @@ -0,0 +1,43 @@ +/* +--- +description: TinyTab - Tiny and simple tab handler for Mootools. + +license: MIT-style + +authors: +- Danillo César de O. Melo + +requires: +- core/1.2.4: '*' + +provides: TinyTab + +... +*/ +(function($) { + this.TinyTab = new Class({ + Implements: Events, + initialize: function(tabs, contents, opt) { + this.tabs = tabs; + this.contents = contents; + if(!opt) opt = {}; + this.css = opt.selectedClass || 'selected'; + this.select(this.tabs[0]); + tabs.each(function(el){ + el.addEvent('click',function(e){ + this.select(el); + e.stop(); + }.bind(this)); + }.bind(this)); + }, + + select: function(el) { + this.tabs.removeClass(this.css); + el.addClass(this.css); + this.contents.setStyle('display','none'); + var content = this.contents[this.tabs.indexOf(el)]; + content.setStyle('display','block'); + this.fireEvent('change',[content,el]); + } + }); +})(document.id);
\ No newline at end of file diff --git a/module/webui/themes/default/js/static/tinytab.min.js b/module/webui/themes/default/js/static/tinytab.min.js new file mode 100644 index 000000000..2f4fa0436 --- /dev/null +++ b/module/webui/themes/default/js/static/tinytab.min.js @@ -0,0 +1 @@ +!function(){this.TinyTab=new Class({Implements:Events,initialize:function(s,t,e){this.tabs=s,this.contents=t,e||(e={}),this.css=e.selectedClass||"selected",this.select(this.tabs[0]),s.each(function(s){s.addEvent("click",function(t){this.select(s),t.stop()}.bind(this))}.bind(this))},select:function(s){this.tabs.removeClass(this.css),s.addClass(this.css),this.contents.setStyle("display","none");var t=this.contents[this.tabs.indexOf(s)];t.setStyle("display","block"),this.fireEvent("change",[t,s])}})}(document.id);
\ No newline at end of file diff --git a/module/webui/themes/default/tml/admin.html b/module/webui/themes/default/tml/admin.html new file mode 100644 index 000000000..ba94f7a74 --- /dev/null +++ b/module/webui/themes/default/tml/admin.html @@ -0,0 +1,98 @@ +{% extends '/default/tml/base.html' %} + +{% block head %} + <script type="text/javascript" src="/default/js/render/admin.min.js"></script> +{% endblock %} + + +{% block title %}{{ _("Administrate") }} - {{ super() }} {% endblock %} +{% block subtitle %}{{ _("Administrate") }}{% endblock %} + +{% block content %} + + <a href="#" id="quit-pyload" style="font-size: large; font-weight: bold;">{{_("Quit pyLoad")}}</a> | + <a href="#" id="restart-pyload" style="font-size: large; font-weight: bold;">{{_("Restart pyLoad")}}</a> + <br> + <br> + + {{ _("To add user or change passwords use:") }} <b>python pyload.py -u</b><br> + {{ _("Important: Admin user have always all permissions!") }} + + <form action="" method="POST"> + <table class="settable wide"> + <thead style="font-size: 11px"> + <th> + {{ _("Name") }} + </th> + <th> + {{ _("Change Password") }} + </th> + <th> + {{ _("Admin") }} + </th> + <th> + {{ _("Permissions") }} + </th> + </thead> + + {% for name, data in users.iteritems() %} + <tr> + <td>{{ name }}</td> + <td><a class="change_password" href="#" id="change_pw|{{name}}">{{ _("change") }}</a></td> + <td><input name="{{ name }}|admin" type="checkbox" {% if data.perms.admin %} + checked="True" {% endif %}"></td> + <td> + <select multiple="multiple" size="{{ permlist|length }}" name="{{ name }}|perms"> + {% for perm in permlist %} + {% if data.perms|getitem(perm) %} + <option selected="selected">{{ perm }}</option> + {% else %} + <option>{{ perm }}</option> + {% endif %} + {% endfor %} + </select> + </td> + </tr> + {% endfor %} + + + </table> + + <button class="styled_button" type="submit">{{ _("Submit") }}</button> + </form> +{% endblock %} +{% block hidden %} + <div id="password_box" class="window_box" style="z-index: 2"> + <form id="password_form" action="/json/change_password" method="POST" enctype="multipart/form-data"> + <h1>{{ _("Change Password") }}</h1> + + <p>{{ _("Enter your current and desired Password.") }}</p> + <label for="user_login">{{ _("User") }} + <span class="small">{{ _("Your username.") }}</span> + </label> + <input id="user_login" name="user_login" type="text" size="20"/> + + <label for="login_current_password">{{ _("Current password") }} + <span class="small">{{ _("The password for this account.") }}</span> + </label> + <input id="login_current_password" name="login_current_password" type="password" size="20"/> + + <label for="login_new_password">{{ _("New password") }} + <span class="small">{{ _("The new password.") }}</span> + </label> + <input id="login_new_password" name="login_new_password" type="password" size="20"/> + + <label for="login_new_password2">{{ _("New password (repeat)") }} + <span class="small">{{ _("Please repeat the new password.") }}</span> + </label> + <input id="login_new_password2" name="login_new_password2" type="password" size="20"/> + + + <button id="login_password_button" type="submit">{{ _("Submit") }}</button> + <button id="login_password_reset" style="margin-left: 0" type="reset">{{ _("Reset") }}</button> + <div class="spacer"></div> + + </form> + + </div> +{% endblock %} diff --git a/module/web/templates/default/base.html b/module/webui/themes/default/tml/base.html index 147c08a37..e2a62a116 100644 --- a/module/web/templates/default/base.html +++ b/module/webui/themes/default/tml/base.html @@ -5,17 +5,17 @@ <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> -<link rel="stylesheet" type="text/css" href="/media/default/css/default.css"/> -<link rel="stylesheet" type="text/css" href="/media/default/css/window.css"/> -<link rel="stylesheet" type="text/css" href="/media/default/css/MooDialog.css"/> +<link rel="stylesheet" type="text/css" href="/default/css/default.min.css"/> +<link rel="stylesheet" type="text/css" href="/default/css/window.min.css"/> +<link rel="stylesheet" type="text/css" href="/default/css/MooDialog.min.css"/> -<script type="text/javascript" src="/media/js/mootools-core-1.4.1.js"></script> -<script type="text/javascript" src="/media/js/mootools-more-1.4.0.1.js"></script> -<script type="text/javascript" src="/media/js/MooDialog_static.js"></script> -<script type="text/javascript" src="/media/js/purr_static.js"></script> +<script type="text/javascript" src="/default/js/static/mootools-core.min.js"></script> +<script type="text/javascript" src="/default/js/static/mootools-more.min.js"></script> +<script type="text/javascript" src="/default/js/static/MooDialog.min.js"></script> +<script type="text/javascript" src="/default/js/static/purr.min.js"></script> -<script type="text/javascript" src="/media/js/base.js"></script> +<script type="text/javascript" src="/default/js/render/base.min.js"></script> <title>{% block title %}pyLoad {{_("Webinterface")}}{% endblock %}</title> @@ -36,7 +36,7 @@ {% if update %} <span> -<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("pyLoad Update available!")}}</span> +<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("New pyLoad version %s available!") % update}}</span> </span> {% endif %} @@ -48,30 +48,30 @@ {% endif %} <span id="cap_info" style="display: {% if captcha %}inline{%else%}none{% endif %}"> -<img src="/media/default/img/images.png" alt="Captcha:" style="vertical-align:middle; margin:2px" /> +<img src="/default/img/images.png" alt="Captcha:" style="vertical-align:middle; margin:2px" /> <span style="font-weight: bold; cursor: pointer; margin-right: 2px;">{{_("Captcha waiting")}}</span> </span> - <img src="/media/default/img/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user.name}}</span> - <ul id="user-actions"> - <li><a href="/logout" class="action logout" rel="nofollow">{{_("Logout")}}</a></li> - {% if user.is_admin %} - <li><a href="/admin" class="action profile" rel="nofollow">{{_("Administrate")}}</a></li> - {% endif %} + <img src="/default/img/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user.name}}</span> + <ul id="user-actions"> + <li><a href="/logout" class="action logout" rel="nofollow">{{_("Logout")}}</a></li> + {% if user.is_admin %} + <li><a href="/admin" class="action profile" rel="nofollow">{{_("Administrate")}}</a></li> + {% endif %} <li><a href="/info" class="action info" rel="nofollow">{{_("Info")}}</a></li> - </ul> + </ul> {% else %} <span style="padding-right: 2px;">{{_("Please Login!")}}</span> {% endif %} {% endblock %} - </div> + </div> - <a href="/"><img id="head-logo" src="/media/default/img/pyload-logo-edited3.5-new-font-small.png" alt="pyLoad" /></a> + <a href="/"><img id="head-logo" src="/default/img/pyload-logo.png" alt="pyLoad" /></a> - <div id="head-menu"> - <ul> + <div id="head-menu"> + <ul> {% macro selected(name, right=False) -%} {% if name in url -%}class="{% if right -%}right {% endif %}selected"{%- endif %} @@ -79,39 +79,39 @@ {%- endmacro %} - {% block menu %} - <li> - <a href="/" title=""><img src="/media/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> - </li> - <li {{ selected('queue') }}> - <a href="/queue/" title=""><img src="/media/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> - </li> - <li {{ selected('collector') }}> - <a href="/collector/" title=""><img src="/media/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> - </li> - <li {{ selected('downloads') }}> - <a href="/downloads/" title=""><img src="/media/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> - </li> -{# <li {{ selected('filemanager') }}>#} -{# <a href="/filemanager/" title=""><img src="/media/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#} -{# </li>#} - <li {{ selected('logs', True) }}> - <a href="/logs/" class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> - </li> - <li {{ selected('settings', True) }}> - <a href="/settings/" class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a> - </li> - {% endblock %} - - </ul> - </div> - - <div style="clear:both;"></div> + {% block menu %} + <li> + <a href="/" title=""><img src="/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> + </li> + <li {{ selected('queue') }}> + <a href="/queue/" title=""><img src="/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> + </li> + <li {{ selected('collector') }}> + <a href="/collector/" title=""><img src="/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> + </li> + <li {{ selected('downloads') }}> + <a href="/downloads/" title=""><img src="/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> + </li> +{# <li {{ selected('filemanager') }}>#} +{# <a href="/filemanager/" title=""><img src="/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#} +{# </li>#} + <li {{ selected('logs', True) }}> + <a href="/logs/" title=""><img src="/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> + </li> + <li {{ selected('settings', True) }}> + <a href="/settings/" title=""><img src="/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a> + </li> + {% endblock %} + + </ul> + </div> + + <div style="clear:both;"></div> </div> {% if perms.STATUS %} <ul id="page-actions2"> - <li id="action_play"><a href="#" class="action play" accesskey="o" rel="nofollow">{{_("Start")}}</a></li> + <li id="action_play"><a href="#" class="action play" accesskey="o" rel="nofollow">{{_("Start")}}</a></li> <li id="action_stop"><a href="#" class="action stop" accesskey="o" rel="nofollow">{{_("Stop")}}</a></li> <li id="action_cancel"><a href="#" class="action cancel" accesskey="o" rel="nofollow">{{_("Cancel")}}</a></li> <li id="action_add"><a href="#" class="action add" accesskey="o" rel="nofollow" >{{_("Add")}}</a></li> @@ -149,20 +149,20 @@ <noscript><h1>Enable JavaScript to use the webinterface.</h1></noscript> {% for message in messages %} - <b><p>{{message}}</p></b> + <b><p>{{message}}</p></b> {% endfor %} <div id="load-indicator" style="opacity: 0; float: right; margin-top: -10px;"> - <img src="/media/default/img/ajax-loader.gif" alt="" style="padding-right: 5px"/> + <img src="/default/img/ajax-loader.gif" alt="" style="padding-right: 5px"/> {{_("loading")}} </div> {% block content %} {% endblock content %} - <hr style="clear: both;" /> + <hr style="clear: both;" /> -<div id="foot">© 2008-2011 pyLoad Team +<div id="foot">© 2008-2014 pyLoad Team <a href="#top" class="action top" accesskey="x"><span>{{_("Back to top")}}</span></a><br /> <!--<div class="breadcrumbs"></div>--> @@ -171,8 +171,8 @@ </div> <div style="display: none;"> - {% include "default/window.html" %} - {% include "default/captcha.html" %} + {% include '/default/tml/window.html' %} + {% include '/default/tml/captcha.html' %} {% block hidden %} {% endblock %} </div> diff --git a/module/webui/themes/default/tml/captcha.html b/module/webui/themes/default/tml/captcha.html new file mode 100644 index 000000000..56892593f --- /dev/null +++ b/module/webui/themes/default/tml/captcha.html @@ -0,0 +1,42 @@ +<!-- Captcha box --> +<div id="cap_box" class="window_box"> + + <form id="cap_form" action="/json/set_captcha" method="POST" enctype="multipart/form-data" onsubmit="return false;"> + + <h1>{{_("Captcha reading")}}</h1> + <p id="cap_title">{{_("Please read the text on the captcha.")}}</p> + + <div id="cap_textual"> + + <input id="cap_id" name="cap_id" type="hidden" value="" /> + + <label>{{_("Captcha")}} + <span class="small">{{_("The captcha.")}}</span> + </label> + <span class="cont"> + <img id="cap_textual_img" src=""> + </span> + + <label>{{_("Text")}} + <span class="small">{{_("Input the text on the captcha.")}}</span> + </label> + <input id="cap_result" name="cap_result" type="text" size="20" /> + + </div> + + <div id="cap_positional" style="text-align: center"> + <img id="cap_positional_img" src="" style="margin: 10px; cursor:pointer"> + </div> + + <div id="button_bar" style="text-align: center"> + <span> + <button id="cap_submit" type="submit" style="margin-left: 0">{{_("Submit")}}</button> + <button id="cap_reset" type="reset" style="margin-left: 0">{{_("Close")}}</button> + </span> + </div> + + <div class="spacer"></div> + + </form> + +</div> diff --git a/module/webui/themes/default/tml/downloads.html b/module/webui/themes/default/tml/downloads.html new file mode 100644 index 000000000..ba0f77c18 --- /dev/null +++ b/module/webui/themes/default/tml/downloads.html @@ -0,0 +1,29 @@ +{% extends '/default/tml/base.html' %} + +{% block title %}Downloads - {{super()}} {% endblock %} + +{% block subtitle %} +{{_("Downloads")}} +{% endblock %} + +{% block content %} + +<ul> + {% for folder in files.folder %} + <li> + {{ folder.name }} + <ul> + {% for file in folder.files %} + <li><a href='get/{{ folder.path|escape }}/{{ file|escape }}'>{{file}}</a></li> + {% endfor %} + </ul> + </li> + {% endfor %} + + {% for file in files.files %} + <li> <a href='get/{{ file|escape }}'>{{ file }}</a></li> + {% endfor %} + +</ul> + +{% endblock %} diff --git a/module/web/templates/default/filemanager.html b/module/webui/themes/default/tml/filemanager.html index 97095c13e..7a370d04c 100644 --- a/module/web/templates/default/filemanager.html +++ b/module/webui/themes/default/tml/filemanager.html @@ -1,8 +1,8 @@ -{% extends 'default/base.html' %} +{% extends '/default/tml/base.html' %} {% block head %} -<script type="text/javascript" src="/filemanager_ui.js"></script> +<script type="text/javascript" src="/default/js/render/filemanager.min.js"></script> <script type="text/javascript"> @@ -26,9 +26,9 @@ document.addEvent("domready", function(){ <span> <b>{{ file.name }}</b> <span class="buttons" style="opacity:0"> - <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/media/default/img/pencil.png" /> - - <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/media/default/img/delete.png" /> + <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/default/img/pencil.png" /> + + <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/default/img/delete.png" /> </span> </span> </li> @@ -39,30 +39,30 @@ document.addEvent("domready", function(){ <input type="hidden" name="path" class="path" value="{{ fld.path }}" /> <input type="hidden" name="name" class="name" value="{{ fld.name }}" /> <span> - <b>{{ fld.name }}</b> - <span class="buttons" style="opacity:0"> - <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/media/default/img/pencil.png" /> - - <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/media/default/img/delete.png" /> - - <img title="{{_("Add subdirectory")}}" class="mkdir" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/media/default/img/add_folder.png" /> - </span> + <b>{{ fld.name }}</b> + <span class="buttons" style="opacity:0"> + <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/default/img/pencil.png" /> + + <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/default/img/delete.png" /> + + <img title="{{_("Add subdirectory")}}" class="mkdir" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/default/img/add_folder.png" /> + </span> </span> {% if (fld.folders|length + fld.files|length) > 0 %} - {% if open %} - <ul> - {% else %} - <ul style="display:none"> - {% endif %} - {% for child in fld.folders %} - {{ display_folder(child) }} - {% endfor %} - {% for child in fld.files %} - {{ display_file(child) }} - {% endfor %} - </ul> + {% if open %} + <ul> + {% else %} + <ul style="display:none"> + {% endif %} + {% for child in fld.folders %} + {{ display_folder(child) }} + {% endfor %} + {% for child in fld.files %} + {{ display_file(child) }} + {% endfor %} + </ul> {% else %} - <div style="display:none">{{ _("Folder is empty") }}</div> + <div style="display:none">{{ _("Folder is empty") }}</div> {% endif %} </li> {%- endmacro %} @@ -75,6 +75,4 @@ document.addEvent("domready", function(){ {{ display_folder(root, true) }} </ul> -{% include "default/rename_directory.html" %} - {% endblock %} diff --git a/module/webui/themes/default/tml/folder.html b/module/webui/themes/default/tml/folder.html new file mode 100644 index 000000000..227a46ba0 --- /dev/null +++ b/module/webui/themes/default/tml/folder.html @@ -0,0 +1,15 @@ +<li class="folder"> + <input type="hidden" name="path" class="path" value="{{ path }}" /> + <input type="hidden" name="name" class="name" value="{{ name }}" /> + <span> + <b>{{ name }}</b> + <span class="buttons" style="opacity:0"> + <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/default/img/pencil.png" /> + + <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/default/img/delete.png" /> + + <img title="{{_("Add subdirectory")}}" class="mkdir" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/default/img/add_folder.png" /> + </span> + </span> + <div style="display:none">{{ _("Folder is empty") }}</div> +</li> diff --git a/module/web/templates/default/home.html b/module/webui/themes/default/tml/home.html index 7359e326c..0fff703b5 100644 --- a/module/web/templates/default/home.html +++ b/module/webui/themes/default/tml/home.html @@ -1,4 +1,4 @@ -{% extends 'default/base.html' %} +{% extends '/default/tml/base.html' %} {% block head %} <script type="text/javascript"> @@ -7,21 +7,21 @@ var em; var operafix = (navigator.userAgent.toLowerCase().search("opera") >= 0); document.addEvent("domready", function(){ - em = new EntryManager(); + em = new EntryManager(); }); var EntryManager = new Class({ initialize: function(){ this.json = new Request.JSON({ - url: "json/links", + url: "json/links", secure: false, async: true, - onSuccess: this.update.bind(this), - initialDelay: 0, - delay: 2500, - limit: 30000 - }); - + onSuccess: this.update.bind(this), + initialDelay: 0, + delay: 2500, + limit: 30000 + }); + this.ids = [{% for link in content %} {% if forloop.last %} {{ link.id }} @@ -29,12 +29,12 @@ var EntryManager = new Class({ {{ link.id }}, {% endif %} {% endfor %}]; - + this.entries = []; this.container = $('LinksAktiv'); - + this.parseFromContent(); - + this.json.startTimer(); }, parseFromContent: function(){ @@ -45,12 +45,12 @@ var EntryManager = new Class({ }, this); }, update: function(data){ - + try{ this.ids = this.entries.map(function(item){ return item.fid }); - + this.ids.filter(function(id){ return !this.ids.contains(id) },data).each(function(id){ @@ -59,13 +59,13 @@ var EntryManager = new Class({ this.entries = this.entries.filter(function(item){return item.fid != this},id); this.ids = this.ids.erase(id) }, this); - + data.links.each(function(link, i){ if (this.ids.contains(link.fid)){ - + var index = this.ids.indexOf(link.fid); this.entries[index].update(link) - + }else{ var entry = new LinkEntry(link.fid); entry.insert(link); @@ -74,7 +74,7 @@ var EntryManager = new Class({ this.container.adopt(entry.elements.tr,entry.elements.pgbTr); entry.fade.start('opacity', 1); entry.fadeBar.start('opacity', 1); - + } }, this) }catch(e){ @@ -129,7 +129,7 @@ var LinkEntry = new Class({ 'html': item.percent+ '% / '+ humanFileSize(item.size-item.bleft) }), remove: new Element('img',{ - 'src': 'media/default/img/control_cancel.png', + 'src': '/default/img/control_cancel.png', 'styles':{ 'vertical-align': 'middle', 'margin-right': '-20px', @@ -150,7 +150,7 @@ var LinkEntry = new Class({ } }) }; - + this.elements.tr.adopt(this.elements.name,this.elements.status,this.elements.info,this.elements.bleft,new Element('td').adopt(this.elements.percent,this.elements.remove)); this.elements.pgbTr.adopt(new Element('td',{'colspan':5}).adopt(this.elements.pgb)); this.initEffects(); @@ -163,11 +163,11 @@ var LinkEntry = new Class({ this.bar = new Fx.Morph(this.elements.pgb, {unit: '%', duration: 5000, link: 'link', fps:30}); this.fade = new Fx.Tween(this.elements.tr); this.fadeBar = new Fx.Tween(this.elements.pgbTr); - + this.elements.remove.addEvent('click', function(){ new Request({method: 'get', url: '/json/abort_link/'+this.id}).send(); }.bind(this)); - + }, update: function(item){ this.elements.name.set('text', item.name); @@ -208,25 +208,25 @@ var LinkEntry = new Class({ {% block menu %} <li class="selected"> - <a href="/" title=""><img src="/media/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> + <a href="/" title=""><img src="/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> </li> <li> - <a href="/queue/" title=""><img src="/media/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> + <a href="/queue/" title=""><img src="/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> </li> <li> - <a href="/collector/" title=""><img src="/media/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> + <a href="/collector/" title=""><img src="/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> </li> <li> - <a href="/downloads/" title=""><img src="/media/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> + <a href="/downloads/" title=""><img src="/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> </li> {#<li>#} -{# <a href="/filemanager/" title=""><img src="/media/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#} +{# <a href="/filemanager/" title=""><img src="/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#} {#</li>#} <li class="right"> - <a href="/logs/" class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> + <a href="/logs/" title=""><img src="/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> </li> <li class="right"> - <a href="/settings/" class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a> + <a href="/settings/" title=""><img src="/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a> </li> {% endblock %} @@ -242,7 +242,7 @@ var LinkEntry = new Class({ </tr> </thead> <tbody id="LinksAktiv"> - + {% for link in content %} <tr id="link_{{ link.id }}"> <td id="link_{{ link.id }}_name">{{ link.name }}</td> @@ -251,7 +251,7 @@ var LinkEntry = new Class({ <td id="link_{{ link.id }}_bleft">{{ link.format_size }}</td> <td> <span id="link_{{ link.id }}_percent">{{ link.percent }}% /{{ link.bleft }}</span> - <img id="link_{{ link.id }}_remove" style="vertical-align: middle; margin-right: -20px; margin-left: 5px; margin-top: -2px; cursor:pointer;" src="media/default/img/control_cancel.png"/> + <img id="link_{{ link.id }}_remove" style="vertical-align: middle; margin-right: -20px; margin-left: 5px; margin-top: -2px; cursor:pointer;" src="/default/img/control_cancel.png"/> </td> </tr> <tr id="link_{{ link.id }}_pgb_tr"> @@ -260,7 +260,7 @@ var LinkEntry = new Class({ </td> </tr> {% endfor %} - + </tbody> </table> -{% endblock %}
\ No newline at end of file +{% endblock %} diff --git a/module/webui/themes/default/tml/info.html b/module/webui/themes/default/tml/info.html new file mode 100644 index 000000000..2deaa6dce --- /dev/null +++ b/module/webui/themes/default/tml/info.html @@ -0,0 +1,81 @@ +{% extends '/default/tml/base.html' %} + +{% block head %} + <script type="text/javascript"> + window.addEvent("domready", function() { + var ul = new Element('ul#twitter_update_list'); + var script1 = new Element('script[src=http://twitter.com/javascripts/blogger.min.js][type=text/javascript]'); + var script2 = new Element('script[src=http://twitter.com/statuses/user_timeline/pyLoad.json?callback=twitterCallback2&count=6][type=text/javascript]'); + $("twitter").adopt(ul, script1, script2); + }); + </script> +{% endblock %} + +{% block title %}{{ _("Information") }} - {{ super() }} {% endblock %} +{% block subtitle %}{{ _("Information") }}{% endblock %} + +{% block content %} + <h3>{{ _("News") }}</h3> + <div id="twitter"></div> + + <h3>{{ _("Support") }}</h3> + + <ul> + <li style="font-weight:bold;"> + <a href="http://pyload.org/wiki" target="_blank">Wiki</a> + | + <a href="http://forum.pyload.org/" target="_blank">Forum</a> + | + <a href="http://pyload.org/irc/" target="_blank">Chat</a> + </li> + <li style="font-weight:bold;"><a href="http://docs.pyload.org" target="_blank">Documentation</a></li> + <li style="font-weight:bold;"><a href="https://bitbucket.org/spoob/pyload/overview" target="_blank">Development</a></li> + <li style="font-weight:bold;"><a href="https://bitbucket.org/spoob/pyload/issues?status=new&status=open" target="_blank">Issue Tracker</a></li> + + </ul> + + <h3>{{ _("System") }}</h3> + <table class="system"> + <tr> + <td>{{ _("Python:") }}</td> + <td>{{ python }}</td> + </tr> + <tr> + <td>{{ _("OS:") }}</td> + <td>{{ os }}</td> + </tr> + <tr> + <td>{{ _("pyLoad version:") }}</td> + <td>{{ version }}</td> + </tr> + <tr> + <td>{{ _("Installation Folder:") }}</td> + <td>{{ folder }}</td> + </tr> + <tr> + <td>{{ _("Config Folder:") }}</td> + <td>{{ config }}</td> + </tr> + <tr> + <td>{{ _("Download Folder:") }}</td> + <td>{{ download }}</td> + </tr> + <tr> + <td>{{ _("Free Space:") }}</td> + <td>{{ freespace }}</td> + </tr> + <tr> + <td>{{ _("Language:") }}</td> + <td>{{ language }}</td> + </tr> + <tr> + <td>{{ _("Webinterface Port:") }}</td> + <td>{{ webif }}</td> + </tr> + <tr> + <td>{{ _("Remote Interface Port:") }}</td> + <td>{{ remote }}</td> + </tr> + </table> + +{% endblock %} diff --git a/module/web/templates/default/login.html b/module/webui/themes/default/tml/login.html index 9e91ad309..089275219 100644 --- a/module/web/templates/default/login.html +++ b/module/webui/themes/default/tml/login.html @@ -1,4 +1,4 @@ -{% extends 'default/base.html' %} +{% extends '/default/tml/base.html' %} {% block title %}{{_("Login")}} - {{super()}} {% endblock %} @@ -27,10 +27,10 @@ {% if errors %} <p>{{_("Your username and password didn't match. Please try again.")}}</p> - {{ _("To reset your login data or add an user run:") }} <b> python pyLoadCore.py -u</b> + {{ _("To reset your login data or add an user run:") }} <b> python pyload.py -u</b> {% endif %} </div> <br> - + {% endblock %} diff --git a/module/webui/themes/default/tml/logout.html b/module/webui/themes/default/tml/logout.html new file mode 100644 index 000000000..196676de5 --- /dev/null +++ b/module/webui/themes/default/tml/logout.html @@ -0,0 +1,9 @@ +{% extends '/default/tml/base.html' %} + +{% block head %} +<meta http-equiv="refresh" content="3; url=/"> +{% endblock %} + +{% block content %} +<p><b>{{_("You were successfully logged out.")}}</b></p> +{% endblock %} diff --git a/module/webui/themes/default/tml/logs.html b/module/webui/themes/default/tml/logs.html new file mode 100644 index 000000000..1706be8a6 --- /dev/null +++ b/module/webui/themes/default/tml/logs.html @@ -0,0 +1,41 @@ +{% extends '/default/tml/base.html' %} + +{% block title %}{{_("Logs")}} - {{super()}} {% endblock %} +{% block subtitle %}{{_("Logs")}}{% endblock %} +{% block head %} +<link rel="stylesheet" type="text/css" href="/default/css/log.min.css"/> +{% endblock %} + +{% block content %} +<div style="clear: both;"></div> + +<div class="logpaginator"><a href="{{ "/logs/1" }}"><< {{_("Start")}}</a> <a href="{{ "/logs/" + iprev|string }}">< {{_("prev")}}</a> <a href="{{ "/logs/" + inext|string }}">{{_("next")}} ></a> <a href="/logs/">{{_("End")}} >></a></div> +<div class="logperpage"> + <form id="logform1" action="" method="POST"> + <label for="reversed">Reversed:</label> + <input type="checkbox" name="reversed" onchange="this.form.submit();" {% if reversed %} checked="checked" {% endif %} /> + <label for="perpage">Lines per page:</label> + <select name="perpage" onchange="this.form.submit();"> + {% for value in perpage_p %} + <option value="{{value.0}}"{% if value.0 == perpage %} selected="selected" {% endif %}>{{value.1}}</option> + {% endfor %} + </select> + </form> +</div> +<div class="logwarn">{{warning}}</div> +<div style="clear: both;"></div> +<div class="logdiv"> + <table class="logtable" cellpadding="0" cellspacing="0"> + {% for line in log %} + <tr><td class="logline">{{line.line}}</td><td>{{line.date}}</td><td class="loglevel">{{line.level}}</td><td>{{line.message}}</td></tr> + {% endfor %} + </table> +</div> +<div class="logform"> +<form id="logform2" action="" method="POST"> + <label for="from">Jump to time:</label><input type="text" name="from" size="15" value="{{from}}"/> + <input type="submit" value="ok" /> +</form> +</div> +<div style="clear: both; height: 10px;"> </div> +{% endblock %} diff --git a/module/webui/themes/default/tml/pathchooser.html b/module/webui/themes/default/tml/pathchooser.html new file mode 100644 index 000000000..8ce9ab072 --- /dev/null +++ b/module/webui/themes/default/tml/pathchooser.html @@ -0,0 +1,76 @@ +<html> +<head> + <script class="javascript"> + function chosen() + { + opener.ifield.value = document.forms[0].p.value; + close(); + } + function exit() + { + close(); + } + function setInvalid() { + document.forms[0].send.disabled = 'disabled'; + document.forms[0].p.style.color = '#FF0000'; + } + function setValid() { + document.forms[0].send.disabled = ''; + document.forms[0].p.style.color = '#000000'; + } + function setFile(file) + { + document.forms[0].p.value = file; + setValid(); + + } + </script> + <link rel="stylesheet" type="text/css" href="/default/css/pathchooser.min.css"/> +</head> +<body{% if type == 'file' %}{% if not oldfile %} onload="setInvalid();"{% endif %}{% endif %}> +<center> + <div id="paths"> + <form method="get" action="?" onSubmit="chosen();" onReset="exit();"> + <input type="text" name="p" value="{{ oldfile|default(cwd) }}" size="60" onfocus="setValid();"> + <input type="submit" value="Ok" name="send"> + </form> + + {% if type == 'folder' %} + <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/pathchooser" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/pathchooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> + {% else %} + <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/filechooser/" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/filechooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> + {% endif %} + </div> + <table border="0" cellspacing="0" cellpadding="3"> + <tr> + <th>{{_("name")}}</th> + <th>{{_("size")}}</th> + <th>{{_("type")}}</th> + <th>{{_("last modified")}}</th> + </tr> + {% if parentdir %} + <tr> + <td colspan="4"> + <a href="{% if type == 'folder' %}{{ "/pathchooser/" + parentdir|quotepath }}{% else %}{{ "/filechooser/" + parentdir|quotepath }}{% endif %}"><span class="parentdir">{{_("parent directory")}}</span></a> + </td> + </tr> + {% endif %} +{% for file in files %} + <tr> + {% if type == 'folder' %} + <td class="name">{% if file.type == 'dir' %}<a href="{{ "/pathchooser/" + file.fullpath|quotepath }}" title="{{ file.fullpath }}"><span class="path_directory">{{ file.name|truncate(25) }}</span></a>{% else %}<span class="path_file" title="{{ file.fullpath }}">{{ file.name|truncate(25) }}{% endif %}</span></td> + {% else %} + <td class="name">{% if file.type == 'dir' %}<a href="{{ "/filechooser/" + file.fullpath|quotepath }}" title="{{ file.fullpath }}"><span class="file_directory">{{ file.name|truncate(25) }}</span></a>{% else %}<a href="#" onclick="setFile('{{ file.fullpath }}');" title="{{ file.fullpath }}"><span class="file_file">{{ file.name|truncate(25) }}{% endif %}</span></a></td> + {% endif %} + <td class="size">{{ file.size|float|filesizeformat }}</td> + <td class="type">{% if file.type == 'dir' %}directory{% else %}{{ file.ext|default("file") }}{% endif %}</td> + <td class="mtime">{{ file.modified|date("d.m.Y - H:i:s") }}</td> + <tr> +<!-- <tr> + <td colspan="4">{{_("no content")}}</td> + </tr> --> +{% endfor %} + </table> + </center> +</body> +</html> diff --git a/module/web/templates/default/queue.html b/module/webui/themes/default/tml/queue.html index 046abbe49..035ee1808 100644 --- a/module/web/templates/default/queue.html +++ b/module/webui/themes/default/tml/queue.html @@ -1,7 +1,7 @@ -{% extends 'default/base.html' %} +{% extends '/default/tml/base.html' %} {% block head %} -<script type="text/javascript" src="/media/js/package_ui.js"></script> +<script type="text/javascript" src="/default/js/render/package.min.js"></script> <script type="text/javascript"> @@ -35,19 +35,19 @@ document.addEvent("domready", function(){ <li> <div id="package_{{package.pid}}" class="package"> <div class="order" style="display: none;">{{ package.order }}</div> - + <div class="packagename" style="cursor: pointer"> - <img class="package_drag" src="/media/default/img/folder.png" style="cursor: move; margin-bottom: -2px"> + <img class="package_drag" src="/default/img/folder.png" style="cursor: move; margin-bottom: -2px"> <span class="name">{{package.name}}</span> <span class="buttons" style="opacity:0"> - <img title="{{_("Delete Package")}}" style="cursor: pointer" width="12px" height="12px" src="/media/default/img/delete.png" /> + <img title="{{_("Delete Package")}}" style="cursor: pointer" width="12px" height="12px" src="/default/img/delete.png" /> - <img title="{{_("Restart Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/arrow_refresh.png" /> + <img title="{{_("Restart Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/default/img/arrow_refresh.png" /> - <img title="{{_("Edit Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/pencil.png" /> + <img title="{{_("Edit Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/default/img/pencil.png" /> - <img title="{{_("Move Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/package_go.png" /> + <img title="{{_("Move Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/default/img/package_go.png" /> </span> </div> {% set progress = (package.linksdone * 100) / package.linkstotal %} @@ -101,4 +101,4 @@ document.addEvent("domready", function(){ </form> </div> -{% endblock %}
\ No newline at end of file +{% endblock %} diff --git a/module/webui/themes/default/tml/settings.html b/module/webui/themes/default/tml/settings.html new file mode 100644 index 000000000..fddc6e35c --- /dev/null +++ b/module/webui/themes/default/tml/settings.html @@ -0,0 +1,204 @@ +{% extends '/default/tml/base.html' %} + +{% block title %}{{ _("Config") }} - {{ super() }} {% endblock %} +{% block subtitle %}{{ _("Config") }}{% endblock %} + +{% block head %} + <script type="text/javascript" src="/default/js/static/tinytab.min.js"></script> + <script type="text/javascript" src="/default/js/static/MooDropMenu.min.js"></script> + <script type="text/javascript" src="/default/js/render/settings.min.js"></script> + +{% endblock %} + +{% block content %} + + <ul id="toptabs" class="tabs"> + <li><a class="selected" href="#">{{ _("General") }}</a></li> + <li><a href="#">{{ _("Plugins") }}</a></li> + <li><a href="#">{{ _("Accounts") }}</a></li> + </ul> + + <div id="tabsback" style="height: 20px; padding-left: 150px; color: white; font-weight: bold;"> + + </div> + + <span id="tabs-body"> + <!-- General --> + <span id="general" class="active tabContent"> + <ul class="nav tabs"> + <li class> + <a>Menu</a> + <ul id="general-menu"> + {% for entry,name in conf.general %} + <nobr> + <li id="general|{{ entry }}">{{ name }}</li> + </nobr> + <br> + {% endfor %} + </ul> + </li> + </ul> + + <form id="general_form" action="" method="POST" autocomplete="off"> + <span id="general_form_content"> + <br> + <h3> {{ _("Choose a section from the menu") }}</h3> + <br> + </span> + + <input id="general|submit" class="styled_button" type="submit" value="{{_("Submit")}}"/> + </form> + </span> + + <!-- Plugins --> + <span id="plugins" class="tabContent"> + <ul class="nav tabs"> + <li class> + <a>Menu</a> + <ul id="plugin-menu"> + {% for entry,name in conf.plugin %} + <nobr> + <li id="plugin|{{ entry }}">{{ name }}</li> + </nobr> + <br> + {% endfor %} + </ul> + </li> + </ul> + + + <form id="plugin_form" action="" method="POST" autocomplete="off"> + + <span id="plugin_form_content"> + <br> + <h3> {{ _("Choose a section from the menu") }}</h3> + <br> + </span> + <input id="plugin|submit" class="styled_button" type="submit" value="{{_("Submit")}}"/> + </form> + + </span> + + <!-- Accounts --> + <span id="accounts" class="tabContent"> + <form id="account_form" action="/json/update_accounts" method="POST"> + + <table class="settable wide"> + + <thead> + <tr> + <th>{{ _("Plugin") }}</th> + <th>{{ _("Name") }}</th> + <th>{{ _("Password") }}</th> + <th>{{ _("Status") }}</th> + <th>{{ _("Premium") }}</th> + <th>{{ _("Valid until") }}</th> + <th>{{ _("Traffic left") }}</th> + <th>{{ _("Time") }}</th> + <th>{{ _("Max Parallel") }}</th> + <th>{{ _("Delete?") }}</th> + </tr> + </thead> + + + {% for account in conf.accs %} + {% set plugin = account.type %} + <tr> + <td> + <span style="padding:5px">{{ plugin }}</span> + </td> + + <td><label for="{{plugin}}|password;{{account.login}}" + style="color:#424242;">{{ account.login }}</label></td> + <td> + <input id="{{plugin}}|password;{{account.login}}" + name="{{plugin}}|password;{{account.login}}" + type="password" size="12"/> + </td> + <td> + {% if account.valid %} + <span style="font-weight: bold; color: #006400;"> + {{ _("valid") }} + {% else %} + <span style="font-weight: bold; color: #8b0000;"> + {{ _("not valid") }} + {% endif %} + </span> + </td> + <td> + {% if account.premium %} + <span style="font-weight: bold; color: #006400;"> + {{ _("yes") }} + {% else %} + <span style="font-weight: bold; color: #8b0000;"> + {{ _("no") }} + {% endif %} + </span> + </td> + <td> + <span style="font-weight: bold;"> + {{ account.validuntil }} + </span> + </td> + <td> + <span style="font-weight: bold;"> + {{ account.trafficleft }} + </span> + </td> + <td> + <input id="{{plugin}}|time;{{account.login}}" + name="{{plugin}}|time;{{account.login}}" type="text" + size="7" value="{{account.options['time']}}"/> + </td> + <td> + <input id="{{plugin}}|limitdl;{{account.login}}" + name="{{plugin}}|limitdl;{{account.login}}" type="text" + size="2" value="{{account.options['limitdl']}}"/> + </td> + <td> + <input id="{{plugin}}|delete;{{account.login}}" + name="{{plugin}}|delete;{{account.login}}" type="checkbox" + value="True"/> + </td> + </tr> + {% endfor %} + </table> + + <button id="account_submit" type="submit" class="styled_button">{{_("Submit")}}</button> + <button id="account_add" style="margin-left: 0" type="submit" class="styled_button">{{_("Add")}}</button> + </form> + </span> + </span> +{% endblock %} +{% block hidden %} +<div id="account_box" class="window_box" style="z-index: 2"> +<form id="add_account_form" action="/json/add_account" method="POST" enctype="multipart/form-data"> +<h1>{{_("Add Account")}}</h1> +<p>{{_("Enter your account data to use premium features.")}}</p> +<label for="account_login">{{_("Login")}} +<span class="small">{{_("Your username.")}}</span> +</label> +<input id="account_login" name="account_login" type="text" size="20" /> + +<label for="account_password">{{_("Password")}} +<span class="small">{{_("The password for this account.")}}</span> +</label> +<input id="account_password" name="account_password" type="password" size="20" /> + +<label for="account_type">{{_("Type")}} +<span class="small">{{_("Choose the hoster for your account.")}}</span> +</label> + <select name=account_type id="account_type"> + {% for type in types|sort %} + <option value="{{ type }}">{{ type }}</option> + {% endfor %} + </select> + +<button id="account_add_button" type="submit">{{_("Add")}}</button> +<button id="account_reset" style="margin-left: 0" type="reset">{{_("Reset")}}</button> +<div class="spacer"></div> + +</form> + +</div> +{% endblock %} diff --git a/module/webui/themes/default/tml/settings_item.html b/module/webui/themes/default/tml/settings_item.html new file mode 100644 index 000000000..6642d34b4 --- /dev/null +++ b/module/webui/themes/default/tml/settings_item.html @@ -0,0 +1,48 @@ +<table class="settable"> + {% if section.outline %} + <tr><th colspan="2">{{ section.outline }}</th></tr> + {% endif %} + {% for okey, option in section.iteritems() %} + {% if okey not in ("desc", "outline") %} + <tr> + <td><label for="{{skey}}|{{okey}}" + style="color:#424242;">{{ option.desc }}:</label></td> + <td> + {% if option.type == "bool" %} + <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> + <option {% if option.value %} selected="selected" + {% endif %}value="True">{{ _("on") }}</option> + <option {% if not option.value %} selected="selected" + {% endif %}value="False">{{ _("off") }}</option> + </select> + {% elif ";" in option.type %} + <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> + {% for entry in option.list %} + <option {% if option.value == entry %} + selected="selected" {% endif %}>{{ entry }}</option> + {% endfor %} + </select> + {% elif option.type == "folder" %} + <input name="{{skey}}|{{okey}}" type="text" + id="{{skey}}|{{okey}}" value="{{option.value}}"/> + <input name="browsebutton" type="button" + onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); pathchooser = window.open('{% if option.value %}{{ "/pathchooser/" + option.value|quotepath }}{% else %}{{ pathroot }}{% endif %}', 'pathchooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); pathchooser.ifield = ifield; window.ifield = ifield;" + value="{{_("Browse")}}"/> + {% elif option.type == "file" %} + <input name="{{skey}}|{{okey}}" type="text" + id="{{skey}}|{{okey}}" value="{{option.value}}"/> + <input name="browsebutton" type="button" + onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); filechooser = window.open('{% if option.value %}{{ "/filechooser/" + option.value|quotepath }}{% else %}{{ fileroot }}{% endif %}', 'filechooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); filechooser.ifield = ifield; window.ifield = ifield;" + value="{{_("Browse")}}"/> + {% elif option.type == "password" %} + <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" + type="password" value="{{option.value}}"/> + {% else %} + <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" + type="text" value="{{option.value}}"/> + {% endif %} + </td> + </tr> + {% endif %} + {% endfor %} +</table> diff --git a/module/web/templates/default/window.html b/module/webui/themes/default/tml/window.html index a11323fe0..e73eba2bd 100644 --- a/module/web/templates/default/window.html +++ b/module/webui/themes/default/tml/window.html @@ -12,7 +12,7 @@ <label for="add_links">{{_("Links")}} <span class="small">{{_("Paste your links here or any text and press the filter button.")}}</span> <span class="small"> {{ _("Filter urls") }} -<img alt="URIParsing" Title="Parse Uri" src="/media/default/img/parseUri.png" style="cursor:pointer; vertical-align: text-bottom;" onclick="parseUri()"/> +<img alt="URIParsing" Title="Parse Uri" src="/default/img/parseUri.png" style="cursor:pointer; vertical-align: text-bottom;" onclick="parseUri()"/> </span> </label> @@ -43,4 +43,4 @@ </form> -</div>
\ No newline at end of file +</div> diff --git a/module/webui/themes/flat/css/MooDialog.css b/module/webui/themes/flat/css/MooDialog.css new file mode 100644 index 000000000..3ba94cafd --- /dev/null +++ b/module/webui/themes/flat/css/MooDialog.css @@ -0,0 +1,84 @@ +/* Created by Arian Stolwijk <http://www.aryweb.nl> */ + +.MooDialog { +/* position: fixed;*/ + margin: 0 auto 0 -350px; + width:600px; + padding:14px; + left:50%; + top: 100px; + + position: absolute; + left: 50%; + z-index: 50000; + + background: #CDCDCD; + color: black; +} + +.MooDialogTitle { + padding-top: 30px; +} + +.MooDialog .title { + position: absolute; + top: 0; + left: 0; + right: 0; + padding: 3px 20px; + background: #b7c4dc; + border-bottom: 1px solid #a1aec5; + font-weight: bold; + text-shadow: 1px 1px 0 #fff; + color: black; + border-radius: 7px; + -moz-border-radius: 7px; + -webkit-border-radius: 7px; +} + +.MooDialog .close { + background: url(../img/control_cancel.png) no-repeat; + width: 16px; + height: 16px; + display: block; + cursor: pointer; + top: -5px; + left: -5px; + position: absolute; +} + +.MooDialog .buttons { + text-align: right; + margin: 0; + padding: 0; + border: 0; + background: none; +} + +.MooDialog .iframe { + width: 100%; + height: 100%; +} + +.MooDialog .textInput { + width: 200px; + float: left; +} + +.MooDialog .MooDialogAlert, +.MooDialog .MooDialogConfirm, +.MooDialog .MooDialogPrompt, +.MooDialog .MooDialogError { + background: url(../img/MooDialog/dialog-warning.png) no-repeat; + padding-left: 40px; + min-height: 40px; +} + +.MooDialog .MooDialogConfirm, +.MooDialog .MooDialogPromt { + background: url(../img/MooDialog/dialog-question.png) no-repeat; +} + +.MooDialog .MooDialogError { + background: url(../img/MooDialog/dialog-error.png) no-repeat; +} diff --git a/module/webui/themes/flat/css/flat.css b/module/webui/themes/flat/css/flat.css new file mode 100644 index 000000000..1a542962f --- /dev/null +++ b/module/webui/themes/flat/css/flat.css @@ -0,0 +1,863 @@ +.hidden { + display:none; +} +.leftalign { + text-align:left; +} +.centeralign { + text-align:center; +} +.rightalign { + text-align:right; +} +.dokuwiki div.plugin_translation ul li a.wikilink1:link, .dokuwiki div.plugin_translation ul li a.wikilink1:hover, .dokuwiki div.plugin_translation ul li a.wikilink1:active, .dokuwiki div.plugin_translation ul li a.wikilink1:visited { + background-color:#000080; + border:none !important; + color:#FFFFFF !important; + margin:0.1em 0.2em; + padding:0 0.2em; + text-decoration:none; +} +.dokuwiki div.plugin_translation ul li a.wikilink2:link, .dokuwiki div.plugin_translation ul li a.wikilink2:hover, .dokuwiki div.plugin_translation ul li a.wikilink2:active, .dokuwiki div.plugin_translation ul li a.wikilink2:visited { + background-color:#808080; + border:none !important; + color:#FFFFFF !important; + margin:0.1em 0.2em; + padding:0 0.2em; + text-decoration:none; +} +.dokuwiki div.plugin_translation ul li a:hover img { + height:15px; + opacity:1; +} +body { + background-color:white; + color:black; + font-family:'Open Sans', sans-serif; + font-size:12px; + font-style:normal; + font-variant:normal; + font-weight:300; + line-height:normal; + margin:0; + padding:0; +} +hr { + border-bottom-color:#AAAAAA; + border-bottom-style:dotted; +} +img { + border:none; +} +form { + background-color:transparent; + border:none; + display:inline; + margin:0; + padding:0; +} +ul li { + margin:5px; +} +textarea { + font-family:monospace; +} +table { + border-collapse:collapse; + margin:0.5em 0; +} +td { + border:1pt solid #ADB9CC; + padding:0.25em; +} +a { + color:#3465A4; + text-decoration:none; +} +a:hover { + text-decoration:underline; +} +option { + border:0 none #FFFFFF; +} +strong.highlight { + background-color:#FFCC99; + padding:1pt; +} +#pagebottom { + clear:both; +} +hr { + background-color:#C0C0C0; + border:none; + color:#C0C0C0; + margin:0.2em 0; +} +.invisible { + border:0; + height:0; + margin:0; + padding:0; + visibility:hidden; +} +.left { + float:left !important; +} +.right { + float:right !important; +} +.center { + text-align:center; +} +div#body-wrapper { + font-size:127%; + padding:40px 40px 10px; +} +div#content { + color:black; + font-size:14px; + line-height:1.5em; + margin-top:-20px; + padding:0; +} +h1, h2, h3, h4, h5, h6 { + background-attachment:scroll; + background-color:transparent; + background-image:none; + background-position:0 0; + background-repeat:repeat repeat; + color:black; + font-family:'Open Sans', sans-serif; + font-weight:normal; + margin:0; + padding:0.5em 0 0.17em; +} +h1 { + font-family:'Open Sans', sans-serif; + font-weight:300; + line-height:1.2em; + margin-bottom:0.1em; + margin-left:-25px; + padding-bottom:0; + margin-left:-25px; +} +h2 { + font-size:150%; +} +h3, h4, h5, h6 { + border-bottom-style:none; + font-weight:bold; +} +h3 { + font-size:132%; +} +h4 { + font-size:116%; +} +h5 { + font-size:100%; +} +h6 { + font-size:80%; +} +ul#page-actions, ul#page-actions-more { + background-color:#ECECEC; + color:black; + float:right; + list-style-type:none; + margin:10px 10px 0; + padding:6px; + white-space:nowrap; +} +ul#user-actions { + background-color:#ECECEC; + color:black; + display:inline; + list-style-type:none; + margin:0; + padding:5px; +} +ul#page-actions li, ul#user-actions li, ul#page-actions-more li { + display:inline; +} +ul#page-actions a, ul#user-actions a, ul#page-actions-more a { + color:black; + display:inline; + margin:0 3px; + padding:2px 0 2px 18px; + text-decoration:none; +} +ul#page-actions a:hover, ul#page-actions a:focus, ul#user-actions a:hover, ul#user-actions a:focus { +} +ul#page-actions2 { + background-color:#ECECEC; + color:black; + float:left; + list-style-type:none; + margin:10px 10px 0; + padding:6px; +} +ul#user-actions2 { + background-color:#ECECEC; + border-bottom-left-radius:3px; + border-bottom-right-radius:3px; + border-top-left-radius:3px; + border-top-right-radius:3px; + color:black; + display:inline; + list-style-type:none; + margin:0; + padding:5px; +} +ul#page-actions2 li, ul#user-actions2 li { + display:inline; +} +ul#page-actions2 a, ul#user-actions2 a { + color:black; + display:inline; + margin:0 3px; + padding:2px 0 2px 18px; + text-decoration:none; +} +ul#page-actions2 a:hover, ul#page-actions2 a:focus, ul#user-actions2 a:hover, ul#user-actions2 a:focus, ul#page-actions-more a:hover, ul#page-actions-more a:focus { + color:#4E7BB4; +} +.hidden { + display:none; +} +a.logout { + background-color:transparent; + background-image:url(../img/user-actions-logout.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.info { + background-color:transparent; + background-image:url(../img/user-info.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.admin { + background-color:transparent; + background-image:url(../img/user-actions-admin.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.profile { + background-color:transparent; + background-image:url(../img/user-actions-profile.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.create, a.edit { + background-color:transparent; + background-image:url(../img/page-tools-edit.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.source, a.show { + background-color:transparent; + background-image:url(../img/page-tools-source.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.revisions { + background-color:transparent; + background-image:url(../img/page-tools-revisions.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.subscribe, a.unsubscribe { + background-color:transparent; + background-image:url(../img/page-tools-subscribe.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.backlink { + background-color:transparent; + background-image:url(../img/page-tools-backlinks.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.play { + background-color:transparent; + background-image:url(../img/control_play.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +.time { + background-color:transparent; + background-image:url(../img/status_None.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; + margin:0 3px; + padding:2px 0 2px 18px; +} +.reconnect { + background-color:transparent; + background-image:url(../img/reconnect.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; + margin:0 3px; + padding:2px 0 2px 18px; +} +a.play:hover { + background-color:transparent; + background-image:url(../img/control_play_blue.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.cancel { + background-color:transparent; + background-image:url(../img/control_cancel.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.cancel:hover { + background-color:transparent; + background-image:url(../img/control_cancel_blue.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.pause { + background-color:transparent; + background-image:url(../img/control_pause.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.pause:hover { + background-color:transparent; + background-image:url(../img/control_pause_blue.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; + font-weight:bold; +} +a.stop { + background-color:transparent; + background-image:url(../img/control_stop.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.stop:hover { + background-color:transparent; + background-image:url(../img/control_stop_blue.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.add { + background-color:transparent; + background-image:url(../img/control_add.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.add:hover { + background-color:transparent; + background-image:url(../img/control_add_blue.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +a.cog { + background-color:transparent; + background-image:url(../img/cog.png); + background-position:0 1px; + background-repeat:no-repeat no-repeat; +} +#head-panel { + background-color:#DDDDDD; + background-position:0 100%; + background-repeat:repeat no-repeat; +} +#head-panel h1 { + color:#EEEEEC; + display:none; + font-size:2.6em; + margin:0; + padding-left:3.3em; + padding-top:0.8em; + text-decoration:none; +} +#head-panel #head-logo { + float:left; + overflow:visible; + padding:11px 8px 0; +} +#head-menu { + float:left; + margin:0; + padding:1em 0 0; + width:100%; +} +#head-menu ul { + list-style:none; + margin:0 1em 0 2em; +} +#head-menu ul li { + float:left; + font-size:14px; + margin:0 0 4px 0.3em; +} +#head-menu ul li.selected, #head-menu ul li:hover { + margin-bottom:0; +} +#head-menu ul li a img { + height:22px; + padding-right:4px; + vertical-align:middle; + width:22px; +} +#head-menu ul li a, #head-menu ul li a:link { + background-color:#EAEAEA; + background-position:0 100%; + background-repeat:repeat no-repeat; + border-color:#CCCCCC #CCCCCC transparent; + color:#555555; + padding:7px 15px 8px; + text-decoration:none; +} +#head-menu ul li a:hover, #head-menu ul li a:focus { + border-bottom-color:transparent; + border-bottom-left-radius:0; + border-bottom-right-radius:0; + border-bottom-style:none; + border-bottom-width:0; + color:#111111; + outline:none; + padding-bottom:7px; +} +#head-menu ul li a:focus { + margin-bottom:-4px; +} +#head-menu ul li.selected a { + background-color:#FFFFFF; + border-bottom-color:transparent; + color:#3566A5; + padding:7px 15px 8px; +} +#head-menu ul li.selected a:hover, #head-menu ul li.selected a:focus { + color:#111111; +} +div#head-search-and-login { + color:white; + float:right; + margin:0 1em 0 0; + padding:7px 7px 5px 5px; + white-space:nowrap; +} +div#head-search-and-login form { + display:inline; + padding:0 3px; +} +div#head-search-and-login form input { + background-color:#EEEEEE; + border:2px solid #888888; + border-bottom-left-radius:3px; + border-bottom-right-radius:3px; + border-top-left-radius:3px; + border-top-right-radius:3px; + font-size:14px; + padding:2px; +} +div#head-search-and-login form input:focus { + background-color:#FFFFFF; +} +#head-search { + font-size:14px; +} +#head-username, #head-password { + font-size:14px; + width:80px; +} +#pageinfo { + clear:both; + color:#888888; + margin:0; + padding:0.6em 0; +} +#foot { + color:#888888; + font-style:normal; + text-align:center; +} +#foot a { + color:#AAAAFF; +} +#foot img { + vertical-align:middle; +} +div.toc { + background-color:#F0F0F0; + border:1px dotted #888888; + float:right; + font-size:95%; + margin:1em 0 1em 1em; +} +div.toc .tocheader { + font-weight:bold; + margin:0.5em 1em; +} +div.toc ol { + margin:1em 0.5em 1em 1em; + padding:0; +} +div.toc ol li { + margin:0 0 0 1em; + padding:0; +} +div.toc ol ol { + margin:0.5em 0.5em 0.5em 1em; + padding:0; +} +div.recentchanges table { + clear:both; +} +div#editor-help { + background-color:#F7F6F2; + border:1px dotted #888888; + font-size:90%; + padding:0 1ex 1ex; +} +div#preview { + margin-top:1em; +} +label.block { + display:block; + font-weight:bold; + text-align:right; +} +label.simple { + display:block; + font-weight:normal; + text-align:left; +} +label.block input.edit { + width:50%; +} +div.editor { + margin:0; +} +table { + border-collapse:collapse; + margin:0.5em 0; +} +td { + border:1pt solid #ADB9CC; + padding:0.25em; +} +td p { + margin:0; + padding:0; +} +.u { + text-decoration:underline; +} +.footnotes ul { + margin:0 0 1em; + padding:0 2em; +} +.footnotes li { + list-style:none; +} +.userpref table, .userpref td { + border:none; +} +#message { + background-color:#EEEEEE; + border-bottom-color:#CCCCCC; + border-bottom-style:solid; + border-bottom-width:2px; + clear:both; + padding:5px 10px; +} +#message p { + font-weight:bold; + margin:5px 0; + padding:0; +} +#message div.buttons { + font-weight:normal; +} +.diff { + width:99%; +} +.diff-title { + background-color:#C0C0C0; +} +.searchresult dd span { + font-weight:400; +} +.boxtext { + color:#000000; + float:none; + font-family:tahoma, arial, sans-serif; + font-size:11px; + padding:3px 0 0 10px; +} +.statusbutton { + cursor:pointer; + float:left; + height:32px; + margin-left:-32px; + margin-right:5px; + opacity:0; + width:32px; +} +.dlsize { + float:left; + padding-right:8px; +} +.dlspeed { + float:left; + padding-right:8px; +} +.package { + margin-bottom:10px; +} +.packagename { + font-weight:300; +} +.child { + margin-left:20px; +} +.child_status { + margin-right:10px; +} +.child_secrow { + font-size:10px; +} +.header, .header th { + background-color:#ECECEC; + font-weight:300; + text-align:left; +} +.progress_bar { + background-color:#00CC00; + height:5px; +} +.queue { + border:none; +} +.queue tr td { + border:none; +} +.header, .header th { + font-weight:normal; + text-align:left; +} +.clearer { + clear:both; + height:1px; +} +.left { + float:left; +} +.right { + float:right; +} +.setfield { + display:table-cell; +} +ul.tabs li a { + border:none; + border-bottom-left-radius:0; + border-bottom-right-radius:0; + border-top-left-radius:5px; + border-top-right-radius:5px; + font-weight:bold; + padding:5px 16px 4px 15px; +} +#tabs span { + display:none; +} +#tabs span.selected { + display:inline; +} +#tabsback { + background-color:#525252; + border-top-left-radius:3px; + border-top-right-radius:30px; + margin:2px 0 0; + padding:6px 4px 1px; +} +ul.tabs { + list-style-type:none; + margin:0; + padding:0 40px 0 0; +} +ul.tabs li { + display:inline; + margin-left:8px; +} +ul.tabs li a { + background-color:#EAEAEA; + border:1px none #C9C3BA; + border-bottom-left-radius:0; + border-bottom-right-radius:0; + border-top-left-radius:5px; + border-top-right-radius:5px; + color:#42454A; + font-weight:bold; + margin:0; + outline:0; + padding:5px 16px 4px 15px; + text-decoration:none; +} +ul.tabs li a.selected, ul.tabs li a:hover { + background-color:white; + border-bottom-left-radius:0; + border-bottom-right-radius:0; + color:#000000; +} +ul.tabs li a:hover { + background-color:#F1F4EE; +} +ul.tabs li a.selected { + background-color:#525252; + color:white; + font-weight:bold; + padding-bottom:5px; +} +#tabs-body { + overflow:hidden; + position:relative; +} +span.tabContent { + border:2px solid #525252; + margin:0; + padding:0 0 10px; +} +#tabs-body > span { + display:none; +} +#tabs-body > span.active { + display:block; +} +.hide { + display:none; +} +.settable { + border:none; + margin:20px; +} +.settable td { + border:none; + margin:0; + padding:5px; +} +.settable th { + padding-bottom:8px; +} +.settable.wide td, .settable.wide th { + padding-left:15px; + padding-right:15px; +} +ul.nav { + list-style:none; + margin:-30px 0 0; + padding:0; + position:absolute; +} +ul.nav li { + float:left; + padding:5px; + position:relative; +} +ul.nav > li a { + background-color:white; + border-left-color:#C9C3BA; + border-right-color:#C9C3BA; + border-style:solid solid none; + border-top-color:#C9C3BA; + border-width:1px 1px medium; + color:black; +} +ul.nav ul { + -webkit-box-shadow:#AAAAAA 1px 1px 5px; + background-color:#F1F1F1; + border:1px solid #AAAAAA; + box-shadow:#AAAAAA 1px 1px 5px; + cursor:pointer; + left:10px; + list-style:none; + margin:0; + padding:0; + position:absolute; + top:26px; +} +ul.nav .open { + display:block; +} +ul.nav .close { + display:none; +} +ul.nav ul li { + float:none; + padding:0; +} +ul.nav ul li a { + background-color:#F1F1F1; + display:block; + font-weight:normal; + padding:3px; + width:130px; +} +ul.nav ul li a:hover { + background-color:#CDCDCD; +} +ul.nav ul ul { + left:137px; + top:0; +} +.purr-wrapper { + margin:10px; +} +.purr-alert { + background-color:#000000; + border-bottom-left-radius:5px; + border-bottom-right-radius:5px; + border-top-left-radius:5px; + border-top-right-radius:5px; + color:#FFFFFF; + font-size:13px; + font-weight:bold; + margin-bottom:10px; + padding:10px; + width:300px; +} +.purr-alert.error { + background-color:#000000; + background-image:url(../img/error.png); + background-position:7px 10px; + background-repeat:no-repeat no-repeat; + color:#FF5555; + padding-left:30px; + width:280px; +} +.purr-alert.success { + background-color:#000000; + background-image:url(../img/success.png); + background-position:7px 10px; + background-repeat:no-repeat no-repeat; + color:#55FF55; + padding-left:30px; + width:280px; +} +.purr-alert.notice { + background-color:#000000; + background-image:url(../img/notice.png); + background-position:7px 10px; + background-repeat:no-repeat no-repeat; + color:#9999FF; + padding-left:30px; + width:280px; +} +table.system { + border:none; + margin-left:10px; +} +table.system td { + border:none; +} +table.system tr > td:first-child { + font-weight:bold; + padding-right:10px; +}
\ No newline at end of file diff --git a/module/webui/themes/flat/css/log.css b/module/webui/themes/flat/css/log.css new file mode 100644 index 000000000..af2ea4fe8 --- /dev/null +++ b/module/webui/themes/flat/css/log.css @@ -0,0 +1,72 @@ + +html, body, #content +{ + height: 100%; +} +#body-wrapper +{ + height: 70%; +} +.logdiv +{ + height: 90%; + width: 100%; + overflow: auto; + border: 2px solid #CCC; + outline: 1px solid #666; + background-color: #FFE; + margin-right: auto; + margin-left: auto; +} +.logform +{ + display: table; + margin: 0 auto 0 auto; + padding-top: 5px; +} +.logtable +{ + + margin: 0px; +} +.logtable td +{ + border: none; + white-space: nowrap; + + + font-family: monospace; + font-size: 16px; + margin: 0px; + padding: 0px 10px 0px 10px; + line-height: 110%; +} +td.logline +{ + background-color: #EEE; + text-align:right; + padding: 0px 5px 0px 5px; +} +td.loglevel +{ + text-align:right; +} +.logperpage +{ + float: right; + padding-bottom: 8px; +} +.logpaginator +{ + float: left; + padding-top: 5px; +} +.logpaginator a +{ + padding: 0px 8px 0px 8px; +} +.logwarn +{ + text-align: center; + color: red; +}
\ No newline at end of file diff --git a/module/webui/themes/flat/css/pathchooser.css b/module/webui/themes/flat/css/pathchooser.css new file mode 100644 index 000000000..894cc335e --- /dev/null +++ b/module/webui/themes/flat/css/pathchooser.css @@ -0,0 +1,68 @@ +table { + width: 90%; + border: 1px dotted #888888; + font-family: sans-serif; + font-size: 10pt; +} + +th { + background-color: #525252; + color: #E0E0E0; +} + +table, tr, td { + background-color: #F0F0F0; +} + +a, a:visited { + text-decoration: none; + font-weight: bold; +} + +#paths { + width: 90%; + text-align: left; +} + +.file_directory { + color: #c0c0c0; +} +.path_directory { + color: #3c3c3c; +} +.file_file { + color: #3c3c3c; +} +.path_file { + color: #c0c0c0; +} + +.parentdir { + color: #000000; + font-size: 10pt; +} +.name { + text-align: left; +} +.size { + text-align: right; +} +.type { + text-align: left; +} +.mtime { + text-align: center; +} + +.path_abs_rel { + color: #3c3c3c; + text-decoration: none; + font-weight: bold; + font-family: sans-serif; + font-size: 10pt; +} + +.path_abs_rel a { + color: #3c3c3c; + font-style: italic; +} diff --git a/module/webui/themes/flat/css/window.css b/module/webui/themes/flat/css/window.css new file mode 100644 index 000000000..12829868b --- /dev/null +++ b/module/webui/themes/flat/css/window.css @@ -0,0 +1,73 @@ +/* ----------- stylized ----------- */ +.window_box h1{ + font-size:14px; + font-weight:bold; + margin-bottom:8px; +} +.window_box p{ + font-size:11px; + color:#666666; + margin-bottom:20px; + border-bottom:solid 1px #b7ddf2; + padding-bottom:10px; +} +.window_box label{ + display:block; + font-weight:bold; + text-align:right; + width:240px; + float:left; +} +.window_box .small{ + color:#666666; + display:block; + font-size:11px; + font-weight:normal; + text-align:right; + width:240px; +} +.window_box select, .window_box input{ + float:left; + font-size:12px; + padding:4px 2px; + border:solid 1px #aacfe4; + width:300px; + margin:2px 0 20px 10px; +} +.window_box .cont{ + float:left; + font-size:12px; + padding: 0px 10px 15px 0px; + width:300px; + margin:0px 0px 0px 10px; +} +.window_box .cont input{ + float: none; + margin: 0px 15px 0px 1px; +} +.window_box textarea{ + float:left; + font-size:12px; + padding:4px 2px; + border:solid 1px #aacfe4; + width:300px; + margin:2px 0 20px 10px; +} +.window_box button, .styled_button{ + clear:both; + margin-left:150px; + width:125px; + height:31px; + background:#666666 url(../img/button.png) no-repeat; + text-align:center; + line-height:31px; + color:#FFFFFF; + font-size:11px; + font-weight:bold; + border: 0px; +} + +.styled_button { + margin-left: 15px; + cursor: pointer; +} diff --git a/module/webui/themes/flat/img/MooDialog/dialog-close.png b/module/webui/themes/flat/img/MooDialog/dialog-close.png Binary files differnew file mode 100644 index 000000000..81ebb88b2 --- /dev/null +++ b/module/webui/themes/flat/img/MooDialog/dialog-close.png diff --git a/module/webui/themes/flat/img/MooDialog/dialog-error.png b/module/webui/themes/flat/img/MooDialog/dialog-error.png Binary files differnew file mode 100644 index 000000000..d70328403 --- /dev/null +++ b/module/webui/themes/flat/img/MooDialog/dialog-error.png diff --git a/module/webui/themes/flat/img/MooDialog/dialog-question.png b/module/webui/themes/flat/img/MooDialog/dialog-question.png Binary files differnew file mode 100644 index 000000000..b0af3db5b --- /dev/null +++ b/module/webui/themes/flat/img/MooDialog/dialog-question.png diff --git a/module/webui/themes/flat/img/MooDialog/dialog-warning.png b/module/webui/themes/flat/img/MooDialog/dialog-warning.png Binary files differnew file mode 100644 index 000000000..aad64d4be --- /dev/null +++ b/module/webui/themes/flat/img/MooDialog/dialog-warning.png diff --git a/module/webui/themes/flat/img/arrow_refresh.png b/module/webui/themes/flat/img/arrow_refresh.png Binary files differnew file mode 100644 index 000000000..b1b6fa4dc --- /dev/null +++ b/module/webui/themes/flat/img/arrow_refresh.png diff --git a/module/webui/themes/flat/img/arrow_right.png b/module/webui/themes/flat/img/arrow_right.png Binary files differnew file mode 100644 index 000000000..68f379fc7 --- /dev/null +++ b/module/webui/themes/flat/img/arrow_right.png diff --git a/module/webui/themes/flat/img/button.png b/module/webui/themes/flat/img/button.png Binary files differnew file mode 100644 index 000000000..bb408a7d6 --- /dev/null +++ b/module/webui/themes/flat/img/button.png diff --git a/module/webui/themes/flat/img/cog.png b/module/webui/themes/flat/img/cog.png Binary files differnew file mode 100644 index 000000000..833f779ac --- /dev/null +++ b/module/webui/themes/flat/img/cog.png diff --git a/module/webui/themes/flat/img/control_add.png b/module/webui/themes/flat/img/control_add.png Binary files differnew file mode 100644 index 000000000..e3f29fab2 --- /dev/null +++ b/module/webui/themes/flat/img/control_add.png diff --git a/module/webui/themes/flat/img/control_add_blue.png b/module/webui/themes/flat/img/control_add_blue.png Binary files differnew file mode 100644 index 000000000..e3f29fab2 --- /dev/null +++ b/module/webui/themes/flat/img/control_add_blue.png diff --git a/module/webui/themes/flat/img/control_cancel.png b/module/webui/themes/flat/img/control_cancel.png Binary files differnew file mode 100644 index 000000000..07c9cad30 --- /dev/null +++ b/module/webui/themes/flat/img/control_cancel.png diff --git a/module/webui/themes/flat/img/control_cancel_blue.png b/module/webui/themes/flat/img/control_cancel_blue.png Binary files differnew file mode 100644 index 000000000..07c9cad30 --- /dev/null +++ b/module/webui/themes/flat/img/control_cancel_blue.png diff --git a/module/webui/themes/flat/img/control_pause.png b/module/webui/themes/flat/img/control_pause.png Binary files differnew file mode 100644 index 000000000..24e3705fa --- /dev/null +++ b/module/webui/themes/flat/img/control_pause.png diff --git a/module/webui/themes/flat/img/control_pause_blue.png b/module/webui/themes/flat/img/control_pause_blue.png Binary files differnew file mode 100644 index 000000000..24e3705fa --- /dev/null +++ b/module/webui/themes/flat/img/control_pause_blue.png diff --git a/module/webui/themes/flat/img/control_play.png b/module/webui/themes/flat/img/control_play.png Binary files differnew file mode 100644 index 000000000..15ced1e21 --- /dev/null +++ b/module/webui/themes/flat/img/control_play.png diff --git a/module/webui/themes/flat/img/control_play_blue.png b/module/webui/themes/flat/img/control_play_blue.png Binary files differnew file mode 100644 index 000000000..15ced1e21 --- /dev/null +++ b/module/webui/themes/flat/img/control_play_blue.png diff --git a/module/webui/themes/flat/img/control_stop.png b/module/webui/themes/flat/img/control_stop.png Binary files differnew file mode 100644 index 000000000..71215ef67 --- /dev/null +++ b/module/webui/themes/flat/img/control_stop.png diff --git a/module/webui/themes/flat/img/control_stop_blue.png b/module/webui/themes/flat/img/control_stop_blue.png Binary files differnew file mode 100644 index 000000000..71215ef67 --- /dev/null +++ b/module/webui/themes/flat/img/control_stop_blue.png diff --git a/module/webui/themes/flat/img/default/add_folder.png b/module/webui/themes/flat/img/default/add_folder.png Binary files differnew file mode 100644 index 000000000..8acbc411b --- /dev/null +++ b/module/webui/themes/flat/img/default/add_folder.png diff --git a/module/webui/themes/flat/img/default/ajax-loader.gif b/module/webui/themes/flat/img/default/ajax-loader.gif Binary files differnew file mode 100644 index 000000000..2fd8e0737 --- /dev/null +++ b/module/webui/themes/flat/img/default/ajax-loader.gif diff --git a/module/webui/themes/flat/img/default/big_button.gif b/module/webui/themes/flat/img/default/big_button.gif Binary files differnew file mode 100644 index 000000000..7680490ea --- /dev/null +++ b/module/webui/themes/flat/img/default/big_button.gif diff --git a/module/webui/themes/flat/img/default/big_button_over.gif b/module/webui/themes/flat/img/default/big_button_over.gif Binary files differnew file mode 100644 index 000000000..2e3ee10d2 --- /dev/null +++ b/module/webui/themes/flat/img/default/big_button_over.gif diff --git a/module/webui/themes/flat/img/default/body.png b/module/webui/themes/flat/img/default/body.png Binary files differnew file mode 100644 index 000000000..7ff1043e0 --- /dev/null +++ b/module/webui/themes/flat/img/default/body.png diff --git a/module/webui/themes/flat/img/default/closebtn.gif b/module/webui/themes/flat/img/default/closebtn.gif Binary files differnew file mode 100644 index 000000000..3e27e6030 --- /dev/null +++ b/module/webui/themes/flat/img/default/closebtn.gif diff --git a/module/webui/themes/flat/img/default/drag_corner.gif b/module/webui/themes/flat/img/default/drag_corner.gif Binary files differnew file mode 100644 index 000000000..befb1adf1 --- /dev/null +++ b/module/webui/themes/flat/img/default/drag_corner.gif diff --git a/module/webui/themes/flat/img/default/full.png b/module/webui/themes/flat/img/default/full.png Binary files differnew file mode 100644 index 000000000..fea52af76 --- /dev/null +++ b/module/webui/themes/flat/img/default/full.png diff --git a/module/webui/themes/flat/img/default/head-menu-recent.png b/module/webui/themes/flat/img/default/head-menu-recent.png Binary files differnew file mode 100644 index 000000000..fc9b0497f --- /dev/null +++ b/module/webui/themes/flat/img/default/head-menu-recent.png diff --git a/module/webui/themes/flat/img/default/head_bg1.png b/module/webui/themes/flat/img/default/head_bg1.png Binary files differnew file mode 100644 index 000000000..f2848c3cc --- /dev/null +++ b/module/webui/themes/flat/img/default/head_bg1.png diff --git a/module/webui/themes/flat/img/default/images.png b/module/webui/themes/flat/img/default/images.png Binary files differnew file mode 100644 index 000000000..184860d1e --- /dev/null +++ b/module/webui/themes/flat/img/default/images.png diff --git a/module/webui/themes/flat/img/default/parseUri.png b/module/webui/themes/flat/img/default/parseUri.png Binary files differnew file mode 100644 index 000000000..937bded9d --- /dev/null +++ b/module/webui/themes/flat/img/default/parseUri.png diff --git a/module/webui/themes/flat/img/default/pyload-logo.png b/module/webui/themes/flat/img/default/pyload-logo.png Binary files differnew file mode 100644 index 000000000..2443cd8b1 --- /dev/null +++ b/module/webui/themes/flat/img/default/pyload-logo.png diff --git a/module/webui/themes/flat/img/default/tab-background.png b/module/webui/themes/flat/img/default/tab-background.png Binary files differnew file mode 100644 index 000000000..29a5d1991 --- /dev/null +++ b/module/webui/themes/flat/img/default/tab-background.png diff --git a/module/webui/themes/flat/img/default/tabs-border-bottom.png b/module/webui/themes/flat/img/default/tabs-border-bottom.png Binary files differnew file mode 100644 index 000000000..02440f428 --- /dev/null +++ b/module/webui/themes/flat/img/default/tabs-border-bottom.png diff --git a/module/webui/themes/flat/img/delete.png b/module/webui/themes/flat/img/delete.png Binary files differnew file mode 100644 index 000000000..4539cff12 --- /dev/null +++ b/module/webui/themes/flat/img/delete.png diff --git a/module/webui/themes/flat/img/error.png b/module/webui/themes/flat/img/error.png Binary files differnew file mode 100644 index 000000000..6c565c99c --- /dev/null +++ b/module/webui/themes/flat/img/error.png diff --git a/module/webui/themes/flat/img/folder.png b/module/webui/themes/flat/img/folder.png Binary files differnew file mode 100644 index 000000000..0b067dd3c --- /dev/null +++ b/module/webui/themes/flat/img/folder.png diff --git a/module/webui/themes/flat/img/head-login.png b/module/webui/themes/flat/img/head-login.png Binary files differnew file mode 100644 index 000000000..6b57515bc --- /dev/null +++ b/module/webui/themes/flat/img/head-login.png diff --git a/module/webui/themes/flat/img/head-menu-collector.png b/module/webui/themes/flat/img/head-menu-collector.png Binary files differnew file mode 100644 index 000000000..bbcbe6406 --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-collector.png diff --git a/module/webui/themes/flat/img/head-menu-config.png b/module/webui/themes/flat/img/head-menu-config.png Binary files differnew file mode 100644 index 000000000..93e8f83ac --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-config.png diff --git a/module/webui/themes/flat/img/head-menu-development.png b/module/webui/themes/flat/img/head-menu-development.png Binary files differnew file mode 100644 index 000000000..33d8b062f --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-development.png diff --git a/module/webui/themes/flat/img/head-menu-download.png b/module/webui/themes/flat/img/head-menu-download.png Binary files differnew file mode 100644 index 000000000..3691deebc --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-download.png diff --git a/module/webui/themes/flat/img/head-menu-home.png b/module/webui/themes/flat/img/head-menu-home.png Binary files differnew file mode 100644 index 000000000..b77bef5eb --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-home.png diff --git a/module/webui/themes/flat/img/head-menu-index.png b/module/webui/themes/flat/img/head-menu-index.png Binary files differnew file mode 100644 index 000000000..8bc6e9604 --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-index.png diff --git a/module/webui/themes/flat/img/head-menu-news.png b/module/webui/themes/flat/img/head-menu-news.png Binary files differnew file mode 100644 index 000000000..44e79a9a9 --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-news.png diff --git a/module/webui/themes/flat/img/head-menu-queue.png b/module/webui/themes/flat/img/head-menu-queue.png Binary files differnew file mode 100644 index 000000000..e4fa41ad8 --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-queue.png diff --git a/module/webui/themes/flat/img/head-menu-wiki.png b/module/webui/themes/flat/img/head-menu-wiki.png Binary files differnew file mode 100644 index 000000000..61b0e54ea --- /dev/null +++ b/module/webui/themes/flat/img/head-menu-wiki.png diff --git a/module/webui/themes/flat/img/head-search-noshadow.png b/module/webui/themes/flat/img/head-search-noshadow.png Binary files differnew file mode 100644 index 000000000..16d39bd06 --- /dev/null +++ b/module/webui/themes/flat/img/head-search-noshadow.png diff --git a/module/webui/themes/flat/img/notice.png b/module/webui/themes/flat/img/notice.png Binary files differnew file mode 100644 index 000000000..a52b067cb --- /dev/null +++ b/module/webui/themes/flat/img/notice.png diff --git a/module/webui/themes/flat/img/package_go.png b/module/webui/themes/flat/img/package_go.png Binary files differnew file mode 100644 index 000000000..80b2c42ee --- /dev/null +++ b/module/webui/themes/flat/img/package_go.png diff --git a/module/webui/themes/flat/img/page-tools-backlinks.png b/module/webui/themes/flat/img/page-tools-backlinks.png Binary files differnew file mode 100644 index 000000000..fb8f55b38 --- /dev/null +++ b/module/webui/themes/flat/img/page-tools-backlinks.png diff --git a/module/webui/themes/flat/img/page-tools-edit.png b/module/webui/themes/flat/img/page-tools-edit.png Binary files differnew file mode 100644 index 000000000..67177cf89 --- /dev/null +++ b/module/webui/themes/flat/img/page-tools-edit.png diff --git a/module/webui/themes/flat/img/page-tools-revisions.png b/module/webui/themes/flat/img/page-tools-revisions.png Binary files differnew file mode 100644 index 000000000..088fe0087 --- /dev/null +++ b/module/webui/themes/flat/img/page-tools-revisions.png diff --git a/module/webui/themes/flat/img/pencil.png b/module/webui/themes/flat/img/pencil.png Binary files differnew file mode 100644 index 000000000..e39c93cd8 --- /dev/null +++ b/module/webui/themes/flat/img/pencil.png diff --git a/module/webui/themes/flat/img/reconnect.png b/module/webui/themes/flat/img/reconnect.png Binary files differnew file mode 100644 index 000000000..cd35c9325 --- /dev/null +++ b/module/webui/themes/flat/img/reconnect.png diff --git a/module/webui/themes/flat/img/status_None.png b/module/webui/themes/flat/img/status_None.png Binary files differnew file mode 100644 index 000000000..1400d3eb3 --- /dev/null +++ b/module/webui/themes/flat/img/status_None.png diff --git a/module/webui/themes/flat/img/status_downloading.png b/module/webui/themes/flat/img/status_downloading.png Binary files differnew file mode 100644 index 000000000..db8ad8cd6 --- /dev/null +++ b/module/webui/themes/flat/img/status_downloading.png diff --git a/module/webui/themes/flat/img/status_failed.png b/module/webui/themes/flat/img/status_failed.png Binary files differnew file mode 100644 index 000000000..6c565c99c --- /dev/null +++ b/module/webui/themes/flat/img/status_failed.png diff --git a/module/webui/themes/flat/img/status_finished.png b/module/webui/themes/flat/img/status_finished.png Binary files differnew file mode 100644 index 000000000..2c4aca40d --- /dev/null +++ b/module/webui/themes/flat/img/status_finished.png diff --git a/module/webui/themes/flat/img/status_offline.png b/module/webui/themes/flat/img/status_offline.png Binary files differnew file mode 100644 index 000000000..6c565c99c --- /dev/null +++ b/module/webui/themes/flat/img/status_offline.png diff --git a/module/webui/themes/flat/img/status_proc.png b/module/webui/themes/flat/img/status_proc.png Binary files differnew file mode 100644 index 000000000..833f779ac --- /dev/null +++ b/module/webui/themes/flat/img/status_proc.png diff --git a/module/webui/themes/flat/img/status_queue.png b/module/webui/themes/flat/img/status_queue.png Binary files differnew file mode 100644 index 000000000..1400d3eb3 --- /dev/null +++ b/module/webui/themes/flat/img/status_queue.png diff --git a/module/webui/themes/flat/img/status_waiting.png b/module/webui/themes/flat/img/status_waiting.png Binary files differnew file mode 100644 index 000000000..fd038175e --- /dev/null +++ b/module/webui/themes/flat/img/status_waiting.png diff --git a/module/webui/themes/flat/img/success.png b/module/webui/themes/flat/img/success.png Binary files differnew file mode 100644 index 000000000..2c4aca40d --- /dev/null +++ b/module/webui/themes/flat/img/success.png diff --git a/module/webui/themes/flat/img/user-actions-logout.png b/module/webui/themes/flat/img/user-actions-logout.png Binary files differnew file mode 100644 index 000000000..d4ef360e8 --- /dev/null +++ b/module/webui/themes/flat/img/user-actions-logout.png diff --git a/module/webui/themes/flat/img/user-actions-profile.png b/module/webui/themes/flat/img/user-actions-profile.png Binary files differnew file mode 100644 index 000000000..9ec410b13 --- /dev/null +++ b/module/webui/themes/flat/img/user-actions-profile.png diff --git a/module/webui/themes/flat/img/user-info.png b/module/webui/themes/flat/img/user-info.png Binary files differnew file mode 100644 index 000000000..345ed52e4 --- /dev/null +++ b/module/webui/themes/flat/img/user-info.png diff --git a/module/webui/themes/flat/js/render/admin.coffee b/module/webui/themes/flat/js/render/admin.coffee new file mode 100644 index 000000000..5afbcbb66 --- /dev/null +++ b/module/webui/themes/flat/js/render/admin.coffee @@ -0,0 +1,58 @@ +root = this + +window.addEvent "domready", -> + + root.passwordDialog = new MooDialog {destroyOnHide: false} + root.passwordDialog.setContent $ 'password_box' + + $("login_password_reset").addEvent "click", (e) -> root.passwordDialog.close() + $("login_password_button").addEvent "click", (e) -> + + newpw = $("login_new_password").get("value") + newpw2 = $("login_new_password2").get("value") + + if newpw is newpw2 + form = $("password_form") + form.set "send", { + onSuccess: (data) -> + root.notify.alert "Success", { + 'className': 'success' + } + onFailure: (data) -> + root.notify.alert "Error", { + 'className': 'error' + } + } + + form.send() + + root.passwordDialog.close() + else + alert '{{_("Passwords did not match.")}}' + + e.stop() + + for item in $$(".change_password") + id = item.get("id") + user = id.split("|")[1] + $("user_login").set("value", user) + item.addEvent "click", (e) -> root.passwordDialog.open() + + $('quit-pyload').addEvent "click", (e) -> + new MooDialog.Confirm "{{_('You are really sure you want to quit pyLoad?')}}", -> + new Request.JSON({ + url: '/api/kill' + method: 'get' + }).send() + , -> + e.stop() + + $('restart-pyload').addEvent "click", (e) -> + new MooDialog.Confirm "{{_('Are you sure you want to restart pyLoad?')}}", -> + new Request.JSON({ + url: '/api/restart' + method: 'get' + onSuccess: (data) -> alert "{{_('pyLoad restarted')}}" + }).send() + , -> + e.stop() diff --git a/module/webui/themes/flat/js/render/admin.min.js b/module/webui/themes/flat/js/render/admin.min.js new file mode 100644 index 000000000..94a5e494d --- /dev/null +++ b/module/webui/themes/flat/js/render/admin.min.js @@ -0,0 +1,3 @@ +{% autoescape true %} +var root;root=this;window.addEvent("domready",function(){var f,c,b,e,a,d;root.passwordDialog=new MooDialog({destroyOnHide:false});root.passwordDialog.setContent($("password_box"));$("login_password_reset").addEvent("click",function(g){return root.passwordDialog.close()});$("login_password_button").addEvent("click",function(j){var h,i,g;i=$("login_new_password").get("value");g=$("login_new_password2").get("value");if(i===g){h=$("password_form");h.set("send",{onSuccess:function(k){return root.notify.alert("Success",{className:"success"})},onFailure:function(k){return root.notify.alert("Error",{className:"error"})}});h.send();root.passwordDialog.close()}else{alert('{{_("Passwords did not match.")}}')}return j.stop()});d=$$(".change_password");for(e=0,a=d.length;e<a;e++){c=d[e];f=c.get("id");b=f.split("|")[1];$("user_login").set("value",b);c.addEvent("click",function(g){return root.passwordDialog.open()})}$("quit-pyload").addEvent("click",function(g){new MooDialog.Confirm("{{_('You are really sure you want to quit pyLoad?')}}",function(){return new Request.JSON({url:"/api/kill",method:"get"}).send()},function(){});return g.stop()});return $("restart-pyload").addEvent("click",function(g){new MooDialog.Confirm("{{_('Are you sure you want to restart pyLoad?')}}",function(){return new Request.JSON({url:"/api/restart",method:"get",onSuccess:function(h){return alert("{{_('pyLoad restarted')}}")}}).send()},function(){});return g.stop()})}); +{% endautoescape %} diff --git a/module/webui/themes/flat/js/render/base.coffee b/module/webui/themes/flat/js/render/base.coffee new file mode 100644 index 000000000..07b8bfb6f --- /dev/null +++ b/module/webui/themes/flat/js/render/base.coffee @@ -0,0 +1,177 @@ +# External scope +root = this + +# helper functions +humanFileSize = (size) -> + filesizename = new Array("B", "KiB", "MiB", "GiB", "TiB", "PiB") + loga = Math.log(size) / Math.log(1024) + i = Math.floor(loga) + a = Math.pow(1024, i) + if size is 0 then "0 B" else (Math.round(size * 100 / a) / 100 + " " + filesizename[i]) + + +parseUri = () -> + oldString = $("add_links").value + regxp = new RegExp('(ht|f)tp(s?):\/\/[a-zA-Z0-9\-\.\/\?=_&%#]+[<| |\"|\'|\r|\n|\t]{1}', 'g') + resu = oldString.match regxp + return if resu == null + res = "" + + for part in resu + if part.indexOf(" ") != -1 + res = res + part.replace(" ", " \n") + else if part.indexOf("\t") != -1 + res = res + part.replace("\t", " \n") + else if part.indexOf("\r") != -1 + res = res + part.replace("\r", " \n") + else if part.indexOf("\"") != -1 + res = res + part.replace("\"", " \n") + else if part.indexOf("<") != -1 + res = res + part.replace("<", " \n") + else if part.indexOf("'") != -1 + res = res + part.replace("'", " \n") + else + res = res + part.replace("\n", " \n") + + $("add_links").value = res + + +Array::remove = (from, to) -> + rest = this.slice((to || from) + 1 || this.length) + this.length = from < 0 ? this.length + from : from + return [] if this.length == 0 + return this.push.apply(this, rest) + + +document.addEvent "domready", -> + + # global notification + root.notify = new Purr { + 'mode': 'top' + 'position': 'center' + } + + root.captchaBox = new MooDialog {destroyOnHide: false} + root.captchaBox.setContent $ 'cap_box' + + root.addBox = new MooDialog {destroyOnHide: false} + root.addBox.setContent $ 'add_box' + + $('add_form').onsubmit = -> + $('add_form').target = 'upload_target' + if $('add_name').value is "" and $('add_file').value is "" + alert '{{_("Please Enter a packagename.")}}' + return false + else + root.addBox.close() + return true + + $('add_reset').addEvent 'click', -> root.addBox.close() + + $('action_add').addEvent 'click', -> $("add_form").reset(); root.addBox.open() + $('action_play').addEvent 'click', -> new Request({method: 'get', url: '/api/unpauseServer'}).send() + $('action_cancel').addEvent 'click', -> new Request({method: 'get', url: '/api/stopAllDownloads'}).send() + $('action_stop').addEvent 'click', -> new Request({method: 'get', url: '/api/pauseServer'}).send() + + + # captcha events + + $('cap_info').addEvent 'click', -> + load_captcha "get", "" + root.captchaBox.open() + $('cap_reset').addEvent 'click', -> root.captchaBox.close() + $('cap_form').addEvent 'submit', (e) -> + submit_captcha() + e.stop() + + $('cap_positional').addEvent 'click', on_captcha_click + + new Request.JSON({ + url: "/json/status" + onSuccess: LoadJsonToContent + secure: false + async: true + initialDelay: 0 + delay: 4000 + limit: 3000 + }).startTimer() + + +LoadJsonToContent = (data) -> + $("speed").set 'text', humanFileSize(data.speed)+"/s" + $("aktiv").set 'text', data.active + $("aktiv_from").set 'text', data.queue + $("aktiv_total").set 'text', data.total + + if data.captcha + if $("cap_info").getStyle("display") != "inline" + $("cap_info").setStyle 'display', 'inline' + root.notify.alert '{{_("New Captcha Request")}}', { + 'className': 'notify' + } + else + $("cap_info").setStyle 'display', 'none' + + + if data.download + $("time").set 'text', ' {{_("on")}}' + $("time").setStyle 'background-color', "#8ffc25" + else + $("time").set 'text', ' {{_("off")}}' + $("time").setStyle 'background-color', "#fc6e26" + + if data.reconnect + $("reconnect").set 'text', ' {{_("on")}}' + $("reconnect").setStyle 'background-color', "#8ffc25" + else + $("reconnect").set 'text', ' {{_("off")}}' + $("reconnect").setStyle 'background-color', "#fc6e26" + + return null + + +set_captcha = (data) -> + $('cap_id').set 'value', data.id + if (data.result_type is 'textual') + $('cap_textual_img').set 'src', data.src + $('cap_title').set 'text', '{{_("Please read the text on the captcha.")}}' + $('cap_submit').setStyle 'display', 'inline' + $('cap_textual').setStyle 'display', 'block' + $('cap_positional').setStyle 'display', 'none' + + else if (data.result_type == 'positional') + $('cap_positional_img').set('src', data.src) + $('cap_title').set('text', '{{_("Please click on the right captcha position.")}}') + $('cap_submit').setStyle('display', 'none') + $('cap_textual').setStyle('display', 'none') + + +load_captcha = (method, post) -> + new Request.JSON({ + url: "/json/set_captcha" + onSuccess: (data) -> set_captcha(data) if data.captcha else clear_captcha() + secure: false + async: true + method: method + }).send(post) + + +clear_captcha = -> + $('cap_textual').setStyle 'display', 'none' + $('cap_textual_img').set 'src', '' + $('cap_positional').setStyle 'display', 'none' + $('cap_positional_img').set 'src', '' + $('cap_title').set 'text', '{{_("No Captchas to read.")}}' + + +submit_captcha = -> + load_captcha("post", "cap_id=" + $('cap_id').get('value') + "&cap_result=" + $('cap_result').get('value') ) + $('cap_result').set('value', '') + + +on_captcha_click = (e) -> + position = e.target.getPosition() + x = e.page.x - position.x + y = e.page.y - position.y + $('cap_result').value = x + "," + y + submit_captcha() diff --git a/module/webui/themes/flat/js/render/base.min.js b/module/webui/themes/flat/js/render/base.min.js new file mode 100644 index 000000000..1ba1d73f9 --- /dev/null +++ b/module/webui/themes/flat/js/render/base.min.js @@ -0,0 +1,3 @@ +{% autoescape true %} +var LoadJsonToContent,clear_captcha,humanFileSize,load_captcha,on_captcha_click,parseUri,root,set_captcha,submit_captcha;root=this;humanFileSize=function(f){var c,d,e,b;d=new Array("B","KiB","MiB","GiB","TiB","PiB");b=Math.log(f)/Math.log(1024);e=Math.floor(b);c=Math.pow(1024,e);if(f===0){return"0 B"}else{return Math.round(f*100/c)/100+" "+d[e]}};parseUri=function(){var b,c,g,e,d,f,a;b=$("add_links").value;g=new RegExp("(ht|f)tp(s?)://[a-zA-Z0-9-./?=_&%#]+[<| |\"|'|\r|\n|\t]{1}","g");d=b.match(g);if(d===null){return}e="";for(f=0,a=d.length;f<a;f++){c=d[f];if(c.indexOf(" ")!==-1){e=e+c.replace(" "," \n")}else{if(c.indexOf("\t")!==-1){e=e+c.replace("\t"," \n")}else{if(c.indexOf("\r")!==-1){e=e+c.replace("\r"," \n")}else{if(c.indexOf('"')!==-1){e=e+c.replace('"'," \n")}else{if(c.indexOf("<")!==-1){e=e+c.replace("<"," \n")}else{if(c.indexOf("'")!==-1){e=e+c.replace("'"," \n")}else{e=e+c.replace("\n"," \n")}}}}}}}return $("add_links").value=e};Array.prototype.remove=function(d,c){var a,b;a=this.slice((c||d)+1||this.length);this.length=(b=d<0)!=null?b:this.length+{from:d};if(this.length===0){return[]}return this.push.apply(this,a)};document.addEvent("domready",function(){root.notify=new Purr({mode:"top",position:"center"});root.captchaBox=new MooDialog({destroyOnHide:false});root.captchaBox.setContent($("cap_box"));root.addBox=new MooDialog({destroyOnHide:false});root.addBox.setContent($("add_box"));$("add_form").onsubmit=function(){$("add_form").target="upload_target";if($("add_name").value===""&&$("add_file").value===""){alert('{{_("Please Enter a packagename.")}}');return false}else{root.addBox.close();return true}};$("add_reset").addEvent("click",function(){return root.addBox.close()});$("action_add").addEvent("click",function(){$("add_form").reset();return root.addBox.open()});$("action_play").addEvent("click",function(){return new Request({method:"get",url:"/api/unpauseServer"}).send()});$("action_cancel").addEvent("click",function(){return new Request({method:"get",url:"/api/stopAllDownloads"}).send()});$("action_stop").addEvent("click",function(){return new Request({method:"get",url:"/api/pauseServer"}).send()});$("cap_info").addEvent("click",function(){load_captcha("get","");return root.captchaBox.open()});$("cap_reset").addEvent("click",function(){return root.captchaBox.close()});$("cap_form").addEvent("submit",function(a){submit_captcha();return a.stop()});$("cap_positional").addEvent("click",on_captcha_click);return new Request.JSON({url:"/json/status",onSuccess:LoadJsonToContent,secure:false,async:true,initialDelay:0,delay:4000,limit:3000}).startTimer()});LoadJsonToContent=function(a){$("speed").set("text",humanFileSize(a.speed)+"/s");$("aktiv").set("text",a.active);$("aktiv_from").set("text",a.queue);$("aktiv_total").set("text",a.total);if(a.captcha){if($("cap_info").getStyle("display")!=="inline"){$("cap_info").setStyle("display","inline");root.notify.alert('{{_("New Captcha Request")}}',{className:"notify"})}}else{$("cap_info").setStyle("display","none")}if(a.download){$("time").set("text",' {{_("on")}}');$("time").setStyle("background-color","#8ffc25")}else{$("time").set("text",' {{_("off")}}');$("time").setStyle("background-color","#fc6e26")}if(a.reconnect){$("reconnect").set("text",' {{_("on")}}');$("reconnect").setStyle("background-color","#8ffc25")}else{$("reconnect").set("text",' {{_("off")}}');$("reconnect").setStyle("background-color","#fc6e26")}return null};set_captcha=function(a){$("cap_id").set("value",a.id);if(a.result_type==="textual"){$("cap_textual_img").set("src",a.src);$("cap_title").set("text",'{{_("Please read the text on the captcha.")}}');$("cap_submit").setStyle("display","inline");$("cap_textual").setStyle("display","block");return $("cap_positional").setStyle("display","none")}else{if(a.result_type==="positional"){$("cap_positional_img").set("src",a.src);$("cap_title").set("text",'{{_("Please click on the right captcha position.")}}');$("cap_submit").setStyle("display","none");return $("cap_textual").setStyle("display","none")}}};load_captcha=function(b,a){return new Request.JSON({url:"/json/set_captcha",onSuccess:function(c){return set_captcha(c)(c.captcha?void 0:clear_captcha())},secure:false,async:true,method:b}).send(a)};clear_captcha=function(){$("cap_textual").setStyle("display","none");$("cap_textual_img").set("src","");$("cap_positional").setStyle("display","none");$("cap_positional_img").set("src","");return $("cap_title").set("text",'{{_("No Captchas to read.")}}')};submit_captcha=function(){load_captcha("post","cap_id="+$("cap_id").get("value")+"&cap_result="+$("cap_result").get("value"));$("cap_result").set("value","");return false};on_captcha_click=function(c){var b,a,d;b=c.target.getPosition();a=c.page.x-b.x;d=c.page.y-b.y;$("cap_result").value=a+","+d;return submit_captcha()}; +{% endautoescape %} diff --git a/module/webui/themes/flat/js/render/package.js b/module/webui/themes/flat/js/render/package.js new file mode 100644 index 000000000..659a8e6fc --- /dev/null +++ b/module/webui/themes/flat/js/render/package.js @@ -0,0 +1,376 @@ +var root = this; + +document.addEvent("domready", function() { + root.load = new Fx.Tween($("load-indicator"), {link: "cancel"}); + root.load.set("opacity", 0); + + + root.packageBox = new MooDialog({destroyOnHide: false}); + root.packageBox.setContent($('pack_box')); + + $('pack_reset').addEvent('click', function() { + $('pack_form').reset(); + root.packageBox.close(); + }); +}); + +function indicateLoad() { + //$("load-indicator").reveal(); + root.load.start("opacity", 1) +} + +function indicateFinish() { + root.load.start("opacity", 0) +} + +function indicateSuccess() { + indicateFinish(); + root.notify.alert('{{_("Success")}}.', { + 'className': 'success' + }); +} + +function indicateFail() { + indicateFinish(); + root.notify.alert('{{_("Failed")}}.', { + 'className': 'error' + }); +} + +var PackageUI = new Class({ + initialize: function(url, type) { + this.url = url; + this.type = type; + this.packages = []; + this.parsePackages(); + + this.sorts = new Sortables($("package-list"), { + constrain: false, + clone: true, + revert: true, + opacity: 0.4, + handle: ".package_drag", + onComplete: this.saveSort.bind(this) + }); + + $("del_finished").addEvent("click", this.deleteFinished.bind(this)); + $("restart_failed").addEvent("click", this.restartFailed.bind(this)); + + }, + + parsePackages: function() { + $("package-list").getChildren("li").each(function(ele) { + var id = ele.getFirst().get("id").match(/[0-9]+/); + this.packages.push(new Package(this, id, ele)) + }.bind(this)) + }, + + loadPackages: function() { + }, + + deleteFinished: function() { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/api/deleteFinished', + onSuccess: function(data) { + if (data.length > 0) { + window.location.reload() + } else { + this.packages.each(function(pack) { + pack.close(); + }); + indicateSuccess(); + } + }.bind(this), + onFailure: indicateFail + }).send(); + }, + + restartFailed: function() { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/api/restartFailed', + onSuccess: function(data) { + this.packages.each(function(pack) { + pack.close(); + }); + indicateSuccess(); + }.bind(this), + onFailure: indicateFail + }).send(); + }, + + startSort: function(ele, copy) { + }, + + saveSort: function(ele, copy) { + var order = []; + this.sorts.serialize(function(li, pos) { + if (li == ele && ele.retrieve("order") != pos) { + order.push(ele.retrieve("pid") + "|" + pos) + } + li.store("order", pos) + }); + if (order.length > 0) { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/json/package_order/' + order[0], + onSuccess: indicateFinish, + onFailure: indicateFail + }).send(); + } + } + +}); + +var Package = new Class({ + initialize: function(ui, id, ele, data) { + this.ui = ui; + this.id = id; + this.linksLoaded = false; + + if (!ele) { + this.createElement(data); + } else { + this.ele = ele; + this.order = ele.getElements("div.order")[0].get("html"); + this.ele.store("order", this.order); + this.ele.store("pid", this.id); + this.parseElement(); + } + + var pname = this.ele.getElements(".packagename")[0]; + this.buttons = new Fx.Tween(this.ele.getElements(".buttons")[0], {link: "cancel"}); + this.buttons.set("opacity", 0); + + pname.addEvent("mouseenter", function(e) { + this.buttons.start("opacity", 1) + }.bind(this)); + + pname.addEvent("mouseleave", function(e) { + this.buttons.start("opacity", 0) + }.bind(this)); + + + }, + + createElement: function() { + alert("create") + }, + + parseElement: function() { + var imgs = this.ele.getElements('img'); + + this.name = this.ele.getElements('.name')[0]; + this.folder = this.ele.getElements('.folder')[0]; + this.password = this.ele.getElements('.password')[0]; + + imgs[1].addEvent('click', this.deletePackage.bind(this)); + imgs[2].addEvent('click', this.restartPackage.bind(this)); + imgs[3].addEvent('click', this.editPackage.bind(this)); + imgs[4].addEvent('click', this.movePackage.bind(this)); + + this.ele.getElement('.packagename').addEvent('click', this.toggle.bind(this)); + + }, + + loadLinks: function() { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/json/package/' + this.id, + onSuccess: this.createLinks.bind(this), + onFailure: indicateFail + }).send(); + }, + + createLinks: function(data) { + var ul = $("sort_children_{id}".substitute({'id': this.id})); + ul.set("html", ""); + data.links.each(function(link) { + link.id = link.fid; + var li = new Element("li", { + 'style': { + 'margin-left': 0 + } + }); + + var html = "<span style='cursor: move' class='child_status sorthandle'><img src='../img/{icon}' style='width: 12px; height:12px;'/></span>\n".substitute({'icon': link.icon}); + html += "<span style='font-size: 15px'><a href=\"{url}\" target=\"_blank\">{name}</a></span><br /><div class='child_secrow'>".substitute({'url': link.url, 'name': link.name}); + html += "<span class='child_status'>{statusmsg}</span>{error} ".substitute({'statusmsg': link.statusmsg, 'error':link.error}); + html += "<span class='child_status'>{format_size}</span>".substitute({'format_size': link.format_size}); + html += "<span class='child_status'>{plugin}</span> ".substitute({'plugin': link.plugin}); + html += "<img title='{{_(\"Delete Link\")}}' style='cursor: pointer;' width='10px' height='10px' src='../img/delete.png' /> "; + html += "<img title='{{_(\"Restart Link\")}}' style='cursor: pointer;margin-left: -4px' width='10px' height='10px' src='../img/arrow_refresh.png' /></div>"; + + var div = new Element("div", { + 'id': "file_" + link.id, + 'class': "child", + 'html': html + }); + + li.store("order", link.order); + li.store("lid", link.id); + + li.adopt(div); + ul.adopt(li); + }); + this.sorts = new Sortables(ul, { + constrain: false, + clone: true, + revert: true, + opacity: 0.4, + handle: ".sorthandle", + onComplete: this.saveSort.bind(this) + }); + this.registerLinkEvents(); + this.linksLoaded = true; + indicateFinish(); + this.toggle(); + }, + + registerLinkEvents: function() { + this.ele.getElements('.child').each(function(child) { + var lid = child.get('id').match(/[0-9]+/); + var imgs = child.getElements('.child_secrow img'); + imgs[0].addEvent('click', function(e) { + new Request({ + method: 'get', + url: '/api/deleteFiles/[' + this + "]", + onSuccess: function() { + $('file_' + this).nix() + }.bind(this), + onFailure: indicateFail + }).send(); + }.bind(lid)); + + imgs[1].addEvent('click', function(e) { + new Request({ + method: 'get', + url: '/api/restartFile/' + this, + onSuccess: function() { + var ele = $('file_' + this); + var imgs = ele.getElements("img"); + imgs[0].set("src", "../img/status_queue.png"); + var spans = ele.getElements(".child_status"); + spans[1].set("html", "queued"); + indicateSuccess(); + }.bind(this), + onFailure: indicateFail + }).send(); + }.bind(lid)); + }); + }, + + toggle: function() { + var child = this.ele.getElement('.children'); + if (child.getStyle('display') == "block") { + child.dissolve(); + } else { + if (!this.linksLoaded) { + this.loadLinks(); + } else { + child.reveal(); + } + } + }, + + + deletePackage: function(event) { + indicateLoad(); + new Request({ + method: 'get', + url: '/api/deletePackages/[' + this.id + "]", + onSuccess: function() { + this.ele.nix(); + indicateFinish(); + }.bind(this), + onFailure: indicateFail + }).send(); + //hide_pack(); + event.stop(); + }, + + restartPackage: function(event) { + indicateLoad(); + new Request({ + method: 'get', + url: '/api/restartPackage/' + this.id, + onSuccess: function() { + this.close(); + indicateSuccess(); + }.bind(this), + onFailure: indicateFail + }).send(); + event.stop(); + }, + + close: function() { + var child = this.ele.getElement('.children'); + if (child.getStyle('display') == "block") { + child.dissolve(); + } + var ul = $("sort_children_{id}".substitute({'id': this.id})); + ul.erase("html"); + this.linksLoaded = false; + }, + + movePackage: function(event) { + indicateLoad(); + new Request({ + method: 'get', + url: '/json/move_package/' + ((this.ui.type + 1) % 2) + "/" + this.id, + onSuccess: function() { + this.ele.nix(); + indicateFinish(); + }.bind(this), + onFailure: indicateFail + }).send(); + event.stop(); + }, + + editPackage: function(event) { + $("pack_form").removeEvents("submit"); + $("pack_form").addEvent("submit", this.savePackage.bind(this)); + + $("pack_id").set("value", this.id); + $("pack_name").set("value", this.name.get("text")); + $("pack_folder").set("value", this.folder.get("text")); + $("pack_pws").set("value", this.password.get("text")); + + root.packageBox.open(); + event.stop(); + }, + + savePackage: function(event) { + $("pack_form").send(); + this.name.set("text", $("pack_name").get("value")); + this.folder.set("text", $("pack_folder").get("value")); + this.password.set("text", $("pack_pws").get("value")); + root.packageBox.close(); + event.stop(); + }, + + saveSort: function(ele, copy) { + var order = []; + this.sorts.serialize(function(li, pos) { + if (li == ele && ele.retrieve("order") != pos) { + order.push(ele.retrieve("lid") + "|" + pos) + } + li.store("order", pos) + }); + if (order.length > 0) { + indicateLoad(); + new Request.JSON({ + method: 'get', + url: '/json/link_order/' + order[0], + onSuccess: indicateFinish, + onFailure: indicateFail + }).send(); + } + } + +}); diff --git a/module/webui/themes/flat/js/render/settings.coffee b/module/webui/themes/flat/js/render/settings.coffee new file mode 100644 index 000000000..d522741b9 --- /dev/null +++ b/module/webui/themes/flat/js/render/settings.coffee @@ -0,0 +1,107 @@ +root = this + +window.addEvent 'domready', -> + root.accountDialog = new MooDialog {destroyOnHide: false} + root.accountDialog.setContent $ 'account_box' + + new TinyTab $$('#toptabs li a'), $$('#tabs-body > span') + + $$('ul.nav').each (nav) -> + new MooDropMenu nav, { + onOpen: (el) -> el.fade 'in' + onClose: (el) -> el.fade 'out' + onInitialize: (el) -> el.fade('hide').set 'tween', {duration:500} + } + + new SettingsUI() + + +class SettingsUI + constructor: -> + @menu = $$ "#general-menu li" + @menu.append $$ "#plugin-menu li" + + @name = $ "tabsback" + @general = $ "general_form_content" + @plugin = $ "plugin_form_content" + + el.addEvent 'click', @menuClick.bind(this) for el in @menu + + $("general|submit").addEvent "click", @configSubmit.bind(this) + $("plugin|submit").addEvent "click", @configSubmit.bind(this) + + $("account_add").addEvent "click", (e) -> + root.accountDialog.open() + e.stop() + + $("account_reset").addEvent "click", (e) -> + root.accountDialog.close() + + $("account_add_button").addEvent "click", @addAccount.bind(this) + $("account_submit").addEvent "click", @submitAccounts.bind(this) + + + menuClick: (e) -> + [category, section] = e.target.get("id").split("|") + name = e.target.get "text" + + + target = if category is "general" then @general else @plugin + target.dissolve() + + new Request({ + "method" : "get" + "url" : "/json/load_config/#{category}/#{section}" + 'onSuccess': (data) => + target.set "html", data + target.reveal() + this.name.set "text", name + }).send() + + + configSubmit: (e) -> + category = e.target.get("id").split("|")[0] + form = $("#{category}_form") + + form.set "send", { + 'method': "post" + 'url': "/json/save_config/#{category}" + "onSuccess" : -> + root.notify.alert '{{ _("Settings saved.")}}', { + 'className': 'success' + } + 'onFailure': -> + root.notify.alert '{{ _("Error occured.")}}', { + 'className': 'error' + } + } + form.send() + e.stop() + + addAccount: (e) -> + form = $ "add_account_form" + form.set "send", { + 'method': "post" + "onSuccess" : -> window.location.reload() + 'onFailure': -> + root.notify.alert '{{_("Error occured.")}}', { + 'className': 'error' + } + } + + form.send() + e.stop() + + submitAccounts: (e) -> + form = $ "account_form" + form.set "send", { + 'method': "post", + "onSuccess" : -> window.location.reload() + 'onFailure': -> + root.notify.alert('{{ _("Error occured.") }}', { + 'className': 'error' + }) + } + + form.send() + e.stop() diff --git a/module/webui/themes/flat/js/render/settings.min.js b/module/webui/themes/flat/js/render/settings.min.js new file mode 100644 index 000000000..41d1cb25a --- /dev/null +++ b/module/webui/themes/flat/js/render/settings.min.js @@ -0,0 +1,3 @@ +{% autoescape true %} +var SettingsUI,root;var __bind=function(a,b){return function(){return a.apply(b,arguments)}};root=this;window.addEvent("domready",function(){root.accountDialog=new MooDialog({destroyOnHide:false});root.accountDialog.setContent($("account_box"));new TinyTab($$("#toptabs li a"),$$("#tabs-body > span"));$$("ul.nav").each(function(a){return new MooDropMenu(a,{onOpen:function(b){return b.fade("in")},onClose:function(b){return b.fade("out")},onInitialize:function(b){return b.fade("hide").set("tween",{duration:500})}})});return new SettingsUI()});SettingsUI=(function(){function a(){var c,e,b,d;this.menu=$$("#general-menu li");this.menu.append($$("#plugin-menu li"));this.name=$("tabsback");this.general=$("general_form_content");this.plugin=$("plugin_form_content");d=this.menu;for(e=0,b=d.length;e<b;e++){c=d[e];c.addEvent("click",this.menuClick.bind(this))}$("general|submit").addEvent("click",this.configSubmit.bind(this));$("plugin|submit").addEvent("click",this.configSubmit.bind(this));$("account_add").addEvent("click",function(f){root.accountDialog.open();return f.stop()});$("account_reset").addEvent("click",function(f){return root.accountDialog.close()});$("account_add_button").addEvent("click",this.addAccount.bind(this));$("account_submit").addEvent("click",this.submitAccounts.bind(this))}a.prototype.menuClick=function(h){var c,b,g,f,d;d=h.target.get("id").split("|"),c=d[0],g=d[1];b=h.target.get("text");f=c==="general"?this.general:this.plugin;f.dissolve();return new Request({method:"get",url:"/json/load_config/"+c+"/"+g,onSuccess:__bind(function(e){f.set("html",e);f.reveal();return this.name.set("text",b)},this)}).send()};a.prototype.configSubmit=function(d){var c,b;c=d.target.get("id").split("|")[0];b=$(""+c+"_form");b.set("send",{method:"post",url:"/json/save_config/"+c,onSuccess:function(){return root.notify.alert('{{ _("Settings saved.")}}',{className:"success"})},onFailure:function(){return root.notify.alert('{{ _("Error occured.")}}',{className:"error"})}});b.send();return d.stop()};a.prototype.addAccount=function(c){var b;b=$("add_account_form");b.set("send",{method:"post",onSuccess:function(){return window.location.reload()},onFailure:function(){return root.notify.alert('{{_("Error occured.")}}',{className:"error"})}});b.send();return c.stop()};a.prototype.submitAccounts=function(c){var b;b=$("account_form");b.set("send",{method:"post",onSuccess:function(){return window.location.reload()},onFailure:function(){return root.notify.alert('{{ _("Error occured.") }}',{className:"error"})}});b.send();return c.stop()};return a})(); +{% endautoescape %} diff --git a/module/webui/themes/flat/js/static/MooDialog.js b/module/webui/themes/flat/js/static/MooDialog.js new file mode 100644 index 000000000..45a52496f --- /dev/null +++ b/module/webui/themes/flat/js/static/MooDialog.js @@ -0,0 +1,140 @@ +/* +--- +name: MooDialog +description: The base class of MooDialog +authors: Arian Stolwijk +license: MIT-style license +requires: [Core/Class, Core/Element, Core/Element.Style, Core/Element.Event] +provides: [MooDialog, Element.MooDialog] +... +*/ + + +var MooDialog = new Class({ + + Implements: [Options, Events], + + options: { + 'class': 'MooDialog', + title: null, + scroll: true, // IE + forceScroll: false, + useEscKey: true, + destroyOnHide: true, + autoOpen: true, + closeButton: true, + onInitialize: function(){ + this.wrapper.setStyle('display', 'none'); + }, + onBeforeOpen: function(){ + this.wrapper.setStyle('display', 'block'); + this.fireEvent('show'); + }, + onBeforeClose: function(){ + this.wrapper.setStyle('display', 'none'); + this.fireEvent('hide'); + }/*, + onOpen: function(){}, + onClose: function(){}, + onShow: function(){}, + onHide: function(){}, + onInitialize: function(wrapper){}, + onContentChange: function(content){}*/ + }, + + initialize: function(options){ + this.setOptions(options); + this.options.inject = this.options.inject || document.body; + options = this.options; + + var wrapper = this.wrapper = new Element('div.' + options['class'].replace(' ', '.')).inject(options.inject); + this.content = new Element('div.content').inject(wrapper); + + if (options.title){ + this.title = new Element('div.title').set('text', options.title).inject(wrapper); + wrapper.addClass('MooDialogTitle'); + } + + if (options.closeButton){ + this.closeButton = new Element('a.close', { + events: {click: this.close.bind(this)} + }).inject(wrapper); + } + + + /*<ie6>*/// IE 6 scroll + if ((options.scroll && Browser.ie6) || options.forceScroll){ + wrapper.setStyle('position', 'absolute'); + var position = wrapper.getPosition(options.inject); + window.addEvent('scroll', function(){ + var scroll = document.getScroll(); + wrapper.setPosition({ + x: position.x + scroll.x, + y: position.y + scroll.y + }); + }); + } + /*</ie6>*/ + + if (options.useEscKey){ + // Add event for the esc key + document.addEvent('keydown', function(e){ + if (e.key == 'esc') this.close(); + }.bind(this)); + } + + this.addEvent('hide', function(){ + if (options.destroyOnHide) this.destroy(); + }.bind(this)); + + this.fireEvent('initialize', wrapper); + }, + + setContent: function(){ + var content = Array.from(arguments); + if (content.length == 1) content = content[0]; + + this.content.empty(); + + var type = typeOf(content); + if (['string', 'number'].contains(type)) this.content.set('text', content); + else this.content.adopt(content); + + this.fireEvent('contentChange', this.content); + + return this; + }, + + open: function(){ + this.fireEvent('beforeOpen', this.wrapper).fireEvent('open'); + this.opened = true; + return this; + }, + + close: function(){ + this.fireEvent('beforeClose', this.wrapper).fireEvent('close'); + this.opened = false; + return this; + }, + + destroy: function(){ + this.wrapper.destroy(); + }, + + toElement: function(){ + return this.wrapper; + } + +}); + + +Element.implement({ + + MooDialog: function(options){ + this.store('MooDialog', + new MooDialog(options).setContent(this).open() + ); + return this; + } + +}); diff --git a/module/webui/themes/flat/js/static/MooDialog.min.js b/module/webui/themes/flat/js/static/MooDialog.min.js new file mode 100644 index 000000000..90b3ae100 --- /dev/null +++ b/module/webui/themes/flat/js/static/MooDialog.min.js @@ -0,0 +1 @@ +var MooDialog=new Class({Implements:[Options,Events],options:{"class":"MooDialog",title:null,scroll:!0,forceScroll:!1,useEscKey:!0,destroyOnHide:!0,autoOpen:!0,closeButton:!0,onInitialize:function(){this.wrapper.setStyle("display","none")},onBeforeOpen:function(){this.wrapper.setStyle("display","block"),this.fireEvent("show")},onBeforeClose:function(){this.wrapper.setStyle("display","none"),this.fireEvent("hide")}},initialize:function(t){this.setOptions(t),this.options.inject=this.options.inject||document.body,t=this.options;var e=this.wrapper=new Element("div."+t["class"].replace(" ",".")).inject(t.inject);if(this.content=new Element("div.content").inject(e),t.title&&(this.title=new Element("div.title").set("text",t.title).inject(e),e.addClass("MooDialogTitle")),t.closeButton&&(this.closeButton=new Element("a.close",{events:{click:this.close.bind(this)}}).inject(e)),t.scroll&&Browser.ie6||t.forceScroll){e.setStyle("position","absolute");var n=e.getPosition(t.inject);window.addEvent("scroll",function(){var t=document.getScroll();e.setPosition({x:n.x+t.x,y:n.y+t.y})})}t.useEscKey&&document.addEvent("keydown",function(t){"esc"==t.key&&this.close()}.bind(this)),this.addEvent("hide",function(){t.destroyOnHide&&this.destroy()}.bind(this)),this.fireEvent("initialize",e)},setContent:function(){var t=Array.from(arguments);1==t.length&&(t=t[0]),this.content.empty();var e=typeOf(t);return["string","number"].contains(e)?this.content.set("text",t):this.content.adopt(t),this.fireEvent("contentChange",this.content),this},open:function(){return this.fireEvent("beforeOpen",this.wrapper).fireEvent("open"),this.opened=!0,this},close:function(){return this.fireEvent("beforeClose",this.wrapper).fireEvent("close"),this.opened=!1,this},destroy:function(){this.wrapper.destroy()},toElement:function(){return this.wrapper}});Element.implement({MooDialog:function(t){return this.store("MooDialog",new MooDialog(t).setContent(this).open()),this}});
\ No newline at end of file diff --git a/module/webui/themes/flat/js/static/MooDropMenu.js b/module/webui/themes/flat/js/static/MooDropMenu.js new file mode 100644 index 000000000..ac0fa1874 --- /dev/null +++ b/module/webui/themes/flat/js/static/MooDropMenu.js @@ -0,0 +1,86 @@ +/* +--- +description: This provides a simple Drop Down menu with infinit levels + +license: MIT-style + +authors: +- Arian Stolwijk + +requires: + - Core/Class.Extras + - Core/Element.Event + - Core/Selectors + +provides: [MooDropMenu, Element.MooDropMenu] + +... +*/ + +var MooDropMenu = new Class({ + + Implements: [Options, Events], + + options: { + onOpen: function(el){ + el.removeClass('close').addClass('open'); + }, + onClose: function(el){ + el.removeClass('open').addClass('close'); + }, + onInitialize: function(el){ + el.removeClass('open').addClass('close'); + }, + mouseoutDelay: 200, + mouseoverDelay: 0, + listSelector: 'ul', + itemSelector: 'li', + openEvent: 'mouseenter', + closeEvent: 'mouseleave' + }, + + initialize: function(menu, options, level){ + this.setOptions(options); + options = this.options; + + var menu = this.menu = document.id(menu); + + menu.getElements(options.itemSelector + ' > ' + options.listSelector).each(function(el){ + + this.fireEvent('initialize', el); + + var parent = el.getParent(options.itemSelector), + timer; + + parent.addEvent(options.openEvent, function(){ + parent.store('DropDownOpen', true); + + clearTimeout(timer); + if (options.mouseoverDelay) timer = this.fireEvent.delay(options.mouseoverDelay, this, ['open', el]); + else this.fireEvent('open', el); + + }.bind(this)).addEvent(options.closeEvent, function(){ + parent.store('DropDownOpen', false); + + clearTimeout(timer); + timer = (function(){ + if (!parent.retrieve('DropDownOpen')) this.fireEvent('close', el); + }).delay(options.mouseoutDelay, this); + + }.bind(this)); + + }, this); + }, + + toElement: function(){ + return this.menu + } + +}); + +/* So you can do like this $('nav').MooDropMenu(); or even $('nav').MooDropMenu().setStyle('border',1); */ +Element.implement({ + MooDropMenu: function(options){ + return this.store('MooDropMenu', new MooDropMenu(this, options)); + } +}); diff --git a/module/webui/themes/flat/js/static/MooDropMenu.min.js b/module/webui/themes/flat/js/static/MooDropMenu.min.js new file mode 100644 index 000000000..552ae247a --- /dev/null +++ b/module/webui/themes/flat/js/static/MooDropMenu.min.js @@ -0,0 +1 @@ +var MooDropMenu=new Class({Implements:[Options,Events],options:{onOpen:function(e){e.removeClass("close").addClass("open")},onClose:function(e){e.removeClass("open").addClass("close")},onInitialize:function(e){e.removeClass("open").addClass("close")},mouseoutDelay:200,mouseoverDelay:0,listSelector:"ul",itemSelector:"li",openEvent:"mouseenter",closeEvent:"mouseleave"},initialize:function(e,o){this.setOptions(o),o=this.options;var e=this.menu=document.id(e);e.getElements(o.itemSelector+" > "+o.listSelector).each(function(e){this.fireEvent("initialize",e);var n,t=e.getParent(o.itemSelector);t.addEvent(o.openEvent,function(){t.store("DropDownOpen",!0),clearTimeout(n),o.mouseoverDelay?n=this.fireEvent.delay(o.mouseoverDelay,this,["open",e]):this.fireEvent("open",e)}.bind(this)).addEvent(o.closeEvent,function(){t.store("DropDownOpen",!1),clearTimeout(n),n=function(){t.retrieve("DropDownOpen")||this.fireEvent("close",e)}.delay(o.mouseoutDelay,this)}.bind(this))},this)},toElement:function(){return this.menu}});Element.implement({MooDropMenu:function(e){return this.store("MooDropMenu",new MooDropMenu(this,e))}});
\ No newline at end of file diff --git a/module/webui/themes/flat/js/static/mootools-core.js b/module/webui/themes/flat/js/static/mootools-core.js new file mode 100644 index 000000000..db83850fd --- /dev/null +++ b/module/webui/themes/flat/js/static/mootools-core.js @@ -0,0 +1,5977 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/core/8423c12ffd6a6bfcde9ea22554aec795 + +packager build: + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady + +... +*/ + +/* +--- + +name: Core + +description: The heart of MooTools. + +license: MIT-style license. + +copyright: Copyright (c) 2006-2014 [Valerio Proietti](http://mad4milk.net/). + +authors: The MooTools production team (http://mootools.net/developers/) + +inspiration: + - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) + - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) + +provides: [Core, MooTools, Type, typeOf, instanceOf, Native] + +... +*/ + +(function(){ + +this.MooTools = { + version: '1.5.0', + build: '0f7b690afee9349b15909f33016a25d2e4d9f4e3' +}; + +// typeOf, instanceOf + +var typeOf = this.typeOf = function(item){ + if (item == null) return 'null'; + if (item.$family != null) return item.$family(); + + if (item.nodeName){ + if (item.nodeType == 1) return 'element'; + if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; + } else if (typeof item.length == 'number'){ + if ('callee' in item) return 'arguments'; + if ('item' in item) return 'collection'; + } + + return typeof item; +}; + +var instanceOf = this.instanceOf = function(item, object){ + if (item == null) return false; + var constructor = item.$constructor || item.constructor; + while (constructor){ + if (constructor === object) return true; + constructor = constructor.parent; + } + /*<ltIE8>*/ + if (!item.hasOwnProperty) return false; + /*</ltIE8>*/ + return item instanceof object; +}; + +// Function overloading + +var Function = this.Function; + +var enumerables = true; +for (var i in {toString: 1}) enumerables = null; +if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; + +Function.prototype.overloadSetter = function(usePlural){ + var self = this; + return function(a, b){ + if (a == null) return this; + if (usePlural || typeof a != 'string'){ + for (var k in a) self.call(this, k, a[k]); + if (enumerables) for (var i = enumerables.length; i--;){ + k = enumerables[i]; + if (a.hasOwnProperty(k)) self.call(this, k, a[k]); + } + } else { + self.call(this, a, b); + } + return this; + }; +}; + +Function.prototype.overloadGetter = function(usePlural){ + var self = this; + return function(a){ + var args, result; + if (typeof a != 'string') args = a; + else if (arguments.length > 1) args = arguments; + else if (usePlural) args = [a]; + if (args){ + result = {}; + for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); + } else { + result = self.call(this, a); + } + return result; + }; +}; + +Function.prototype.extend = function(key, value){ + this[key] = value; +}.overloadSetter(); + +Function.prototype.implement = function(key, value){ + this.prototype[key] = value; +}.overloadSetter(); + +// From + +var slice = Array.prototype.slice; + +Function.from = function(item){ + return (typeOf(item) == 'function') ? item : function(){ + return item; + }; +}; + +Array.from = function(item){ + if (item == null) return []; + return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; +}; + +Number.from = function(item){ + var number = parseFloat(item); + return isFinite(number) ? number : null; +}; + +String.from = function(item){ + return item + ''; +}; + +// hide, protect + +Function.implement({ + + hide: function(){ + this.$hidden = true; + return this; + }, + + protect: function(){ + this.$protected = true; + return this; + } + +}); + +// Type + +var Type = this.Type = function(name, object){ + if (name){ + var lower = name.toLowerCase(); + var typeCheck = function(item){ + return (typeOf(item) == lower); + }; + + Type['is' + name] = typeCheck; + if (object != null){ + object.prototype.$family = (function(){ + return lower; + }).hide(); + + } + } + + if (object == null) return null; + + object.extend(this); + object.$constructor = Type; + object.prototype.$constructor = object; + + return object; +}; + +var toString = Object.prototype.toString; + +Type.isEnumerable = function(item){ + return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); +}; + +var hooks = {}; + +var hooksOf = function(object){ + var type = typeOf(object.prototype); + return hooks[type] || (hooks[type] = []); +}; + +var implement = function(name, method){ + if (method && method.$hidden) return; + + var hooks = hooksOf(this); + + for (var i = 0; i < hooks.length; i++){ + var hook = hooks[i]; + if (typeOf(hook) == 'type') implement.call(hook, name, method); + else hook.call(this, name, method); + } + + var previous = this.prototype[name]; + if (previous == null || !previous.$protected) this.prototype[name] = method; + + if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ + return method.apply(item, slice.call(arguments, 1)); + }); +}; + +var extend = function(name, method){ + if (method && method.$hidden) return; + var previous = this[name]; + if (previous == null || !previous.$protected) this[name] = method; +}; + +Type.implement({ + + implement: implement.overloadSetter(), + + extend: extend.overloadSetter(), + + alias: function(name, existing){ + implement.call(this, name, this.prototype[existing]); + }.overloadSetter(), + + mirror: function(hook){ + hooksOf(this).push(hook); + return this; + } + +}); + +new Type('Type', Type); + +// Default Types + +var force = function(name, object, methods){ + var isType = (object != Object), + prototype = object.prototype; + + if (isType) object = new Type(name, object); + + for (var i = 0, l = methods.length; i < l; i++){ + var key = methods[i], + generic = object[key], + proto = prototype[key]; + + if (generic) generic.protect(); + if (isType && proto) object.implement(key, proto.protect()); + } + + if (isType){ + var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]); + object.forEachMethod = function(fn){ + if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){ + fn.call(prototype, prototype[methods[i]], methods[i]); + } + for (var key in prototype) fn.call(prototype, prototype[key], key); + }; + } + + return force; +}; + +force('String', String, [ + 'charAt', 'charCodeAt', 'concat', 'contains', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', + 'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase' +])('Array', Array, [ + 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', + 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' +])('Number', Number, [ + 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' +])('Function', Function, [ + 'apply', 'call', 'bind' +])('RegExp', RegExp, [ + 'exec', 'test' +])('Object', Object, [ + 'create', 'defineProperty', 'defineProperties', 'keys', + 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', + 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' +])('Date', Date, ['now']); + +Object.extend = extend.overloadSetter(); + +Date.extend('now', function(){ + return +(new Date); +}); + +new Type('Boolean', Boolean); + +// fixes NaN returning as Number + +Number.prototype.$family = function(){ + return isFinite(this) ? 'number' : 'null'; +}.hide(); + +// Number.random + +Number.extend('random', function(min, max){ + return Math.floor(Math.random() * (max - min + 1) + min); +}); + +// forEach, each + +var hasOwnProperty = Object.prototype.hasOwnProperty; +Object.extend('forEach', function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); + } +}); + +Object.each = Object.forEach; + +Array.implement({ + + /*<!ES5>*/ + forEach: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) fn.call(bind, this[i], i, this); + } + }, + /*</!ES5>*/ + + each: function(fn, bind){ + Array.forEach(this, fn, bind); + return this; + } + +}); + +// Array & Object cloning, Object merging and appending + +var cloneOf = function(item){ + switch (typeOf(item)){ + case 'array': return item.clone(); + case 'object': return Object.clone(item); + default: return item; + } +}; + +Array.implement('clone', function(){ + var i = this.length, clone = new Array(i); + while (i--) clone[i] = cloneOf(this[i]); + return clone; +}); + +var mergeOne = function(source, key, current){ + switch (typeOf(current)){ + case 'object': + if (typeOf(source[key]) == 'object') Object.merge(source[key], current); + else source[key] = Object.clone(current); + break; + case 'array': source[key] = current.clone(); break; + default: source[key] = current; + } + return source; +}; + +Object.extend({ + + merge: function(source, k, v){ + if (typeOf(k) == 'string') return mergeOne(source, k, v); + for (var i = 1, l = arguments.length; i < l; i++){ + var object = arguments[i]; + for (var key in object) mergeOne(source, key, object[key]); + } + return source; + }, + + clone: function(object){ + var clone = {}; + for (var key in object) clone[key] = cloneOf(object[key]); + return clone; + }, + + append: function(original){ + for (var i = 1, l = arguments.length; i < l; i++){ + var extended = arguments[i] || {}; + for (var key in extended) original[key] = extended[key]; + } + return original; + } + +}); + +// Object-less types + +['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ + new Type(name); +}); + +// Unique ID + +var UID = Date.now(); + +String.extend('uniqueID', function(){ + return (UID++).toString(36); +}); + + + +})(); + + +/* +--- + +name: Array + +description: Contains Array Prototypes like each, contains, and erase. + +license: MIT-style license. + +requires: [Type] + +provides: Array + +... +*/ + +Array.implement({ + + /*<!ES5>*/ + every: function(fn, bind){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ + if ((i in this) && !fn.call(bind, this[i], i, this)) return false; + } + return true; + }, + + filter: function(fn, bind){ + var results = []; + for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){ + value = this[i]; + if (fn.call(bind, value, i, this)) results.push(value); + } + return results; + }, + + indexOf: function(item, from){ + var length = this.length >>> 0; + for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){ + if (this[i] === item) return i; + } + return -1; + }, + + map: function(fn, bind){ + var length = this.length >>> 0, results = Array(length); + for (var i = 0; i < length; i++){ + if (i in this) results[i] = fn.call(bind, this[i], i, this); + } + return results; + }, + + some: function(fn, bind){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ + if ((i in this) && fn.call(bind, this[i], i, this)) return true; + } + return false; + }, + /*</!ES5>*/ + + clean: function(){ + return this.filter(function(item){ + return item != null; + }); + }, + + invoke: function(methodName){ + var args = Array.slice(arguments, 1); + return this.map(function(item){ + return item[methodName].apply(item, args); + }); + }, + + associate: function(keys){ + var obj = {}, length = Math.min(this.length, keys.length); + for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; + return obj; + }, + + link: function(object){ + var result = {}; + for (var i = 0, l = this.length; i < l; i++){ + for (var key in object){ + if (object[key](this[i])){ + result[key] = this[i]; + delete object[key]; + break; + } + } + } + return result; + }, + + contains: function(item, from){ + return this.indexOf(item, from) != -1; + }, + + append: function(array){ + this.push.apply(this, array); + return this; + }, + + getLast: function(){ + return (this.length) ? this[this.length - 1] : null; + }, + + getRandom: function(){ + return (this.length) ? this[Number.random(0, this.length - 1)] : null; + }, + + include: function(item){ + if (!this.contains(item)) this.push(item); + return this; + }, + + combine: function(array){ + for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); + return this; + }, + + erase: function(item){ + for (var i = this.length; i--;){ + if (this[i] === item) this.splice(i, 1); + } + return this; + }, + + empty: function(){ + this.length = 0; + return this; + }, + + flatten: function(){ + var array = []; + for (var i = 0, l = this.length; i < l; i++){ + var type = typeOf(this[i]); + if (type == 'null') continue; + array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); + } + return array; + }, + + pick: function(){ + for (var i = 0, l = this.length; i < l; i++){ + if (this[i] != null) return this[i]; + } + return null; + }, + + hexToRgb: function(array){ + if (this.length != 3) return null; + var rgb = this.map(function(value){ + if (value.length == 1) value += value; + return parseInt(value, 16); + }); + return (array) ? rgb : 'rgb(' + rgb + ')'; + }, + + rgbToHex: function(array){ + if (this.length < 3) return null; + if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; + var hex = []; + for (var i = 0; i < 3; i++){ + var bit = (this[i] - 0).toString(16); + hex.push((bit.length == 1) ? '0' + bit : bit); + } + return (array) ? hex : '#' + hex.join(''); + } + +}); + + + + +/* +--- + +name: String + +description: Contains String Prototypes like camelCase, capitalize, test, and toInt. + +license: MIT-style license. + +requires: [Type, Array] + +provides: String + +... +*/ + +String.implement({ + + //<!ES6> + contains: function(string, index){ + return (index ? String(this).slice(index) : String(this)).indexOf(string) > -1; + }, + //</!ES6> + + test: function(regex, params){ + return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); + }, + + trim: function(){ + return String(this).replace(/^\s+|\s+$/g, ''); + }, + + clean: function(){ + return String(this).replace(/\s+/g, ' ').trim(); + }, + + camelCase: function(){ + return String(this).replace(/-\D/g, function(match){ + return match.charAt(1).toUpperCase(); + }); + }, + + hyphenate: function(){ + return String(this).replace(/[A-Z]/g, function(match){ + return ('-' + match.charAt(0).toLowerCase()); + }); + }, + + capitalize: function(){ + return String(this).replace(/\b[a-z]/g, function(match){ + return match.toUpperCase(); + }); + }, + + escapeRegExp: function(){ + return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + hexToRgb: function(array){ + var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); + return (hex) ? hex.slice(1).hexToRgb(array) : null; + }, + + rgbToHex: function(array){ + var rgb = String(this).match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHex(array) : null; + }, + + substitute: function(object, regexp){ + return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ + if (match.charAt(0) == '\\') return match.slice(1); + return (object[name] != null) ? object[name] : ''; + }); + } + +}); + + + + +/* +--- + +name: Number + +description: Contains Number Prototypes like limit, round, times, and ceil. + +license: MIT-style license. + +requires: Type + +provides: Number + +... +*/ + +Number.implement({ + + limit: function(min, max){ + return Math.min(max, Math.max(min, this)); + }, + + round: function(precision){ + precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); + return Math.round(this * precision) / precision; + }, + + times: function(fn, bind){ + for (var i = 0; i < this; i++) fn.call(bind, i, this); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + } + +}); + +Number.alias('each', 'times'); + +(function(math){ + var methods = {}; + math.each(function(name){ + if (!Number[name]) methods[name] = function(){ + return Math[name].apply(null, [this].concat(Array.from(arguments))); + }; + }); + Number.implement(methods); +})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); + + +/* +--- + +name: Function + +description: Contains Function Prototypes like create, bind, pass, and delay. + +license: MIT-style license. + +requires: Type + +provides: Function + +... +*/ + +Function.extend({ + + attempt: function(){ + for (var i = 0, l = arguments.length; i < l; i++){ + try { + return arguments[i](); + } catch (e){} + } + return null; + } + +}); + +Function.implement({ + + attempt: function(args, bind){ + try { + return this.apply(bind, Array.from(args)); + } catch (e){} + + return null; + }, + + /*<!ES5-bind>*/ + bind: function(that){ + var self = this, + args = arguments.length > 1 ? Array.slice(arguments, 1) : null, + F = function(){}; + + var bound = function(){ + var context = that, length = arguments.length; + if (this instanceof bound){ + F.prototype = self.prototype; + context = new F; + } + var result = (!args && !length) + ? self.call(context) + : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments); + return context == that ? result : context; + }; + return bound; + }, + /*</!ES5-bind>*/ + + pass: function(args, bind){ + var self = this; + if (args != null) args = Array.from(args); + return function(){ + return self.apply(bind, args || arguments); + }; + }, + + delay: function(delay, bind, args){ + return setTimeout(this.pass((args == null ? [] : args), bind), delay); + }, + + periodical: function(periodical, bind, args){ + return setInterval(this.pass((args == null ? [] : args), bind), periodical); + } + +}); + + + + +/* +--- + +name: Object + +description: Object generic methods + +license: MIT-style license. + +requires: Type + +provides: [Object, Hash] + +... +*/ + +(function(){ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +Object.extend({ + + subset: function(object, keys){ + var results = {}; + for (var i = 0, l = keys.length; i < l; i++){ + var k = keys[i]; + if (k in object) results[k] = object[k]; + } + return results; + }, + + map: function(object, fn, bind){ + var results = {}; + for (var key in object){ + if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object); + } + return results; + }, + + filter: function(object, fn, bind){ + var results = {}; + for (var key in object){ + var value = object[key]; + if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value; + } + return results; + }, + + every: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false; + } + return true; + }, + + some: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true; + } + return false; + }, + + keys: function(object){ + var keys = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) keys.push(key); + } + return keys; + }, + + values: function(object){ + var values = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) values.push(object[key]); + } + return values; + }, + + getLength: function(object){ + return Object.keys(object).length; + }, + + keyOf: function(object, value){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && object[key] === value) return key; + } + return null; + }, + + contains: function(object, value){ + return Object.keyOf(object, value) != null; + }, + + toQueryString: function(object, base){ + var queryString = []; + + Object.each(object, function(value, key){ + if (base) key = base + '[' + key + ']'; + var result; + switch (typeOf(value)){ + case 'object': result = Object.toQueryString(value, key); break; + case 'array': + var qs = {}; + value.each(function(val, i){ + qs[i] = val; + }); + result = Object.toQueryString(qs, key); + break; + default: result = key + '=' + encodeURIComponent(value); + } + if (value != null) queryString.push(result); + }); + + return queryString.join('&'); + } + +}); + +})(); + + + + +/* +--- + +name: Browser + +description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. + +license: MIT-style license. + +requires: [Array, Function, Number, String] + +provides: [Browser, Window, Document] + +... +*/ + +(function(){ + +var document = this.document; +var window = document.window = this; + +var parse = function(ua, platform){ + ua = ua.toLowerCase(); + platform = (platform ? platform.toLowerCase() : ''); + + var UA = ua.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/) || [null, 'unknown', 0]; + + if (UA[1] == 'trident'){ + UA[1] = 'ie'; + if (UA[4]) UA[2] = UA[4]; + } else if (UA[1] == 'crios') { + UA[1] = 'chrome'; + } + + var platform = ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]; + if (platform == 'win') platform = 'windows'; + + return { + extend: Function.prototype.extend, + name: (UA[1] == 'version') ? UA[3] : UA[1], + version: parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), + platform: platform + }; +}; + +var Browser = this.Browser = parse(navigator.userAgent, navigator.platform); + +if (Browser.ie){ + Browser.version = document.documentMode; +} + +Browser.extend({ + Features: { + xpath: !!(document.evaluate), + air: !!(window.runtime), + query: !!(document.querySelector), + json: !!(window.JSON) + }, + parseUA: parse +}); + + + +// Request + +Browser.Request = (function(){ + + var XMLHTTP = function(){ + return new XMLHttpRequest(); + }; + + var MSXML2 = function(){ + return new ActiveXObject('MSXML2.XMLHTTP'); + }; + + var MSXML = function(){ + return new ActiveXObject('Microsoft.XMLHTTP'); + }; + + return Function.attempt(function(){ + XMLHTTP(); + return XMLHTTP; + }, function(){ + MSXML2(); + return MSXML2; + }, function(){ + MSXML(); + return MSXML; + }); + +})(); + +Browser.Features.xhr = !!(Browser.Request); + + + +// String scripts + +Browser.exec = function(text){ + if (!text) return text; + if (window.execScript){ + window.execScript(text); + } else { + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.text = text; + document.head.appendChild(script); + document.head.removeChild(script); + } + return text; +}; + +String.implement('stripScripts', function(exec){ + var scripts = ''; + var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){ + scripts += code + '\n'; + return ''; + }); + if (exec === true) Browser.exec(scripts); + else if (typeOf(exec) == 'function') exec(scripts, text); + return text; +}); + +// Window, Document + +Browser.extend({ + Document: this.Document, + Window: this.Window, + Element: this.Element, + Event: this.Event +}); + +this.Window = this.$constructor = new Type('Window', function(){}); + +this.$family = Function.from('window').hide(); + +Window.mirror(function(name, method){ + window[name] = method; +}); + +this.Document = document.$constructor = new Type('Document', function(){}); + +document.$family = Function.from('document').hide(); + +Document.mirror(function(name, method){ + document[name] = method; +}); + +document.html = document.documentElement; +if (!document.head) document.head = document.getElementsByTagName('head')[0]; + +if (document.execCommand) try { + document.execCommand("BackgroundImageCache", false, true); +} catch (e){} + +/*<ltIE9>*/ +if (this.attachEvent && !this.addEventListener){ + var unloadEvent = function(){ + this.detachEvent('onunload', unloadEvent); + document.head = document.html = document.window = null; + }; + this.attachEvent('onunload', unloadEvent); +} + +// IE fails on collections and <select>.options (refers to <select>) +var arrayFrom = Array.from; +try { + arrayFrom(document.html.childNodes); +} catch(e){ + Array.from = function(item){ + if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ + var i = item.length, array = new Array(i); + while (i--) array[i] = item[i]; + return array; + } + return arrayFrom(item); + }; + + var prototype = Array.prototype, + slice = prototype.slice; + ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ + var method = prototype[name]; + Array[name] = function(item){ + return method.apply(Array.from(item), slice.call(arguments, 1)); + }; + }); +} +/*</ltIE9>*/ + + + +})(); + + +/* +--- + +name: Event + +description: Contains the Event Type, to make the event object cross-browser. + +license: MIT-style license. + +requires: [Window, Document, Array, Function, String, Object] + +provides: Event + +... +*/ + +(function() { + +var _keys = {}; + +var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){ + if (!win) win = window; + event = event || win.event; + if (event.$extended) return event; + this.event = event; + this.$extended = true; + this.shift = event.shiftKey; + this.control = event.ctrlKey; + this.alt = event.altKey; + this.meta = event.metaKey; + var type = this.type = event.type; + var target = event.target || event.srcElement; + while (target && target.nodeType == 3) target = target.parentNode; + this.target = document.id(target); + + if (type.indexOf('key') == 0){ + var code = this.code = (event.which || event.keyCode); + this.key = _keys[code]; + if (type == 'keydown' || type == 'keyup'){ + if (code > 111 && code < 124) this.key = 'f' + (code - 111); + else if (code > 95 && code < 106) this.key = code - 96; + } + if (this.key == null) this.key = String.fromCharCode(code).toLowerCase(); + } else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){ + var doc = win.document; + doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; + this.page = { + x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, + y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop + }; + this.client = { + x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, + y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY + }; + if (type == 'DOMMouseScroll' || type == 'mousewheel') + this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; + + this.rightClick = (event.which == 3 || event.button == 2); + if (type == 'mouseover' || type == 'mouseout'){ + var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; + while (related && related.nodeType == 3) related = related.parentNode; + this.relatedTarget = document.id(related); + } + } else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){ + this.rotation = event.rotation; + this.scale = event.scale; + this.targetTouches = event.targetTouches; + this.changedTouches = event.changedTouches; + var touches = this.touches = event.touches; + if (touches && touches[0]){ + var touch = touches[0]; + this.page = {x: touch.pageX, y: touch.pageY}; + this.client = {x: touch.clientX, y: touch.clientY}; + } + } + + if (!this.client) this.client = {}; + if (!this.page) this.page = {}; +}); + +DOMEvent.implement({ + + stop: function(){ + return this.preventDefault().stopPropagation(); + }, + + stopPropagation: function(){ + if (this.event.stopPropagation) this.event.stopPropagation(); + else this.event.cancelBubble = true; + return this; + }, + + preventDefault: function(){ + if (this.event.preventDefault) this.event.preventDefault(); + else this.event.returnValue = false; + return this; + } + +}); + +DOMEvent.defineKey = function(code, key){ + _keys[code] = key; + return this; +}; + +DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true); + +DOMEvent.defineKeys({ + '38': 'up', '40': 'down', '37': 'left', '39': 'right', + '27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab', + '46': 'delete', '13': 'enter' +}); + +})(); + + + + + + +/* +--- + +name: Class + +description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. + +license: MIT-style license. + +requires: [Array, String, Function, Number] + +provides: Class + +... +*/ + +(function(){ + +var Class = this.Class = new Type('Class', function(params){ + if (instanceOf(params, Function)) params = {initialize: params}; + + var newClass = function(){ + reset(this); + if (newClass.$prototyping) return this; + this.$caller = null; + var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; + this.$caller = this.caller = null; + return value; + }.extend(this).implement(params); + + newClass.$constructor = Class; + newClass.prototype.$constructor = newClass; + newClass.prototype.parent = parent; + + return newClass; +}); + +var parent = function(){ + if (!this.$caller) throw new Error('The method "parent" cannot be called.'); + var name = this.$caller.$name, + parent = this.$caller.$owner.parent, + previous = (parent) ? parent.prototype[name] : null; + if (!previous) throw new Error('The method "' + name + '" has no parent.'); + return previous.apply(this, arguments); +}; + +var reset = function(object){ + for (var key in object){ + var value = object[key]; + switch (typeOf(value)){ + case 'object': + var F = function(){}; + F.prototype = value; + object[key] = reset(new F); + break; + case 'array': object[key] = value.clone(); break; + } + } + return object; +}; + +var wrap = function(self, key, method){ + if (method.$origin) method = method.$origin; + var wrapper = function(){ + if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); + var caller = this.caller, current = this.$caller; + this.caller = current; this.$caller = wrapper; + var result = method.apply(this, arguments); + this.$caller = current; this.caller = caller; + return result; + }.extend({$owner: self, $origin: method, $name: key}); + return wrapper; +}; + +var implement = function(key, value, retain){ + if (Class.Mutators.hasOwnProperty(key)){ + value = Class.Mutators[key].call(this, value); + if (value == null) return this; + } + + if (typeOf(value) == 'function'){ + if (value.$hidden) return this; + this.prototype[key] = (retain) ? value : wrap(this, key, value); + } else { + Object.merge(this.prototype, key, value); + } + + return this; +}; + +var getInstance = function(klass){ + klass.$prototyping = true; + var proto = new klass; + delete klass.$prototyping; + return proto; +}; + +Class.implement('implement', implement.overloadSetter()); + +Class.Mutators = { + + Extends: function(parent){ + this.parent = parent; + this.prototype = getInstance(parent); + }, + + Implements: function(items){ + Array.from(items).each(function(item){ + var instance = new item; + for (var key in instance) implement.call(this, key, instance[key], true); + }, this); + } +}; + +})(); + + +/* +--- + +name: Class.Extras + +description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. + +license: MIT-style license. + +requires: Class + +provides: [Class.Extras, Chain, Events, Options] + +... +*/ + +(function(){ + +this.Chain = new Class({ + + $chain: [], + + chain: function(){ + this.$chain.append(Array.flatten(arguments)); + return this; + }, + + callChain: function(){ + return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; + }, + + clearChain: function(){ + this.$chain.empty(); + return this; + } + +}); + +var removeOn = function(string){ + return string.replace(/^on([A-Z])/, function(full, first){ + return first.toLowerCase(); + }); +}; + +this.Events = new Class({ + + $events: {}, + + addEvent: function(type, fn, internal){ + type = removeOn(type); + + + + this.$events[type] = (this.$events[type] || []).include(fn); + if (internal) fn.internal = true; + return this; + }, + + addEvents: function(events){ + for (var type in events) this.addEvent(type, events[type]); + return this; + }, + + fireEvent: function(type, args, delay){ + type = removeOn(type); + var events = this.$events[type]; + if (!events) return this; + args = Array.from(args); + events.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + removeEvent: function(type, fn){ + type = removeOn(type); + var events = this.$events[type]; + if (events && !fn.internal){ + var index = events.indexOf(fn); + if (index != -1) delete events[index]; + } + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + if (events) events = removeOn(events); + for (type in this.$events){ + if (events && events != type) continue; + var fns = this.$events[type]; + for (var i = fns.length; i--;) if (i in fns){ + this.removeEvent(type, fns[i]); + } + } + return this; + } + +}); + +this.Options = new Class({ + + setOptions: function(){ + var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments)); + if (this.addEvent) for (var option in options){ + if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; + this.addEvent(option, options[option]); + delete options[option]; + } + return this; + } + +}); + +})(); + + +/* +--- +name: Slick.Parser +description: Standalone CSS3 Selector parser +provides: Slick.Parser +... +*/ + +;(function(){ + +var parsed, + separatorIndex, + combinatorIndex, + reversed, + cache = {}, + reverseCache = {}, + reUnescape = /\\/g; + +var parse = function(expression, isReversed){ + if (expression == null) return null; + if (expression.Slick === true) return expression; + expression = ('' + expression).replace(/^\s+|\s+$/g, ''); + reversed = !!isReversed; + var currentCache = (reversed) ? reverseCache : cache; + if (currentCache[expression]) return currentCache[expression]; + parsed = { + Slick: true, + expressions: [], + raw: expression, + reverse: function(){ + return parse(this.raw, true); + } + }; + separatorIndex = -1; + while (expression != (expression = expression.replace(regexp, parser))); + parsed.length = parsed.expressions.length; + return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed; +}; + +var reverseCombinator = function(combinator){ + if (combinator === '!') return ' '; + else if (combinator === ' ') return '!'; + else if ((/^!/).test(combinator)) return combinator.replace(/^!/, ''); + else return '!' + combinator; +}; + +var reverse = function(expression){ + var expressions = expression.expressions; + for (var i = 0; i < expressions.length; i++){ + var exp = expressions[i]; + var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)}; + + for (var j = 0; j < exp.length; j++){ + var cexp = exp[j]; + if (!cexp.reverseCombinator) cexp.reverseCombinator = ' '; + cexp.combinator = cexp.reverseCombinator; + delete cexp.reverseCombinator; + } + + exp.reverse().push(last); + } + return expression; +}; + +var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License + return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){ + return '\\' + match; + }); +}; + +var regexp = new RegExp( +/* +#!/usr/bin/env ruby +puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'') +__END__ + "(?x)^(?:\ + \\s* ( , ) \\s* # Separator \n\ + | \\s* ( <combinator>+ ) \\s* # Combinator \n\ + | ( \\s+ ) # CombinatorChildren \n\ + | ( <unicode>+ | \\* ) # Tag \n\ + | \\# ( <unicode>+ ) # ID \n\ + | \\. ( <unicode>+ ) # ClassName \n\ + | # Attribute \n\ + \\[ \ + \\s* (<unicode1>+) (?: \ + \\s* ([*^$!~|]?=) (?: \ + \\s* (?:\ + ([\"']?)(.*?)\\9 \ + )\ + ) \ + )? \\s* \ + \\](?!\\]) \n\ + | :+ ( <unicode>+ )(?:\ + \\( (?:\ + (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\ + ) \\)\ + )?\ + )" +*/ + "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)" + .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']') + .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') + .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') +); + +function parser( + rawMatch, + + separator, + combinator, + combinatorChildren, + + tagName, + id, + className, + + attributeKey, + attributeOperator, + attributeQuote, + attributeValue, + + pseudoMarker, + pseudoClass, + pseudoQuote, + pseudoClassQuotedValue, + pseudoClassValue +){ + if (separator || separatorIndex === -1){ + parsed.expressions[++separatorIndex] = []; + combinatorIndex = -1; + if (separator) return ''; + } + + if (combinator || combinatorChildren || combinatorIndex === -1){ + combinator = combinator || ' '; + var currentSeparator = parsed.expressions[separatorIndex]; + if (reversed && currentSeparator[combinatorIndex]) + currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator); + currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'}; + } + + var currentParsed = parsed.expressions[separatorIndex][combinatorIndex]; + + if (tagName){ + currentParsed.tag = tagName.replace(reUnescape, ''); + + } else if (id){ + currentParsed.id = id.replace(reUnescape, ''); + + } else if (className){ + className = className.replace(reUnescape, ''); + + if (!currentParsed.classList) currentParsed.classList = []; + if (!currentParsed.classes) currentParsed.classes = []; + currentParsed.classList.push(className); + currentParsed.classes.push({ + value: className, + regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') + }); + + } else if (pseudoClass){ + pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue; + pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null; + + if (!currentParsed.pseudos) currentParsed.pseudos = []; + currentParsed.pseudos.push({ + key: pseudoClass.replace(reUnescape, ''), + value: pseudoClassValue, + type: pseudoMarker.length == 1 ? 'class' : 'element' + }); + + } else if (attributeKey){ + attributeKey = attributeKey.replace(reUnescape, ''); + attributeValue = (attributeValue || '').replace(reUnescape, ''); + + var test, regexp; + + switch (attributeOperator){ + case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break; + case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break; + case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break; + case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break; + case '=' : test = function(value){ + return attributeValue == value; + }; break; + case '*=' : test = function(value){ + return value && value.indexOf(attributeValue) > -1; + }; break; + case '!=' : test = function(value){ + return attributeValue != value; + }; break; + default : test = function(value){ + return !!value; + }; + } + + if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){ + return false; + }; + + if (!test) test = function(value){ + return value && regexp.test(value); + }; + + if (!currentParsed.attributes) currentParsed.attributes = []; + currentParsed.attributes.push({ + key: attributeKey, + operator: attributeOperator, + value: attributeValue, + test: test + }); + + } + + return ''; +}; + +// Slick NS + +var Slick = (this.Slick || {}); + +Slick.parse = function(expression){ + return parse(expression); +}; + +Slick.escapeRegExp = escapeRegExp; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); + + +/* +--- +name: Slick.Finder +description: The new, superfast css selector engine. +provides: Slick.Finder +requires: Slick.Parser +... +*/ + +;(function(){ + +var local = {}, + featuresCache = {}, + toString = Object.prototype.toString; + +// Feature / Bug detection + +local.isNativeCode = function(fn){ + return (/\{\s*\[native code\]\s*\}/).test('' + fn); +}; + +local.isXML = function(document){ + return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') || + (document.nodeType == 9 && document.documentElement.nodeName != 'HTML'); +}; + +local.setDocument = function(document){ + + // convert elements / window arguments to document. if document cannot be extrapolated, the function returns. + var nodeType = document.nodeType; + if (nodeType == 9); // document + else if (nodeType) document = document.ownerDocument; // node + else if (document.navigator) document = document.document; // window + else return; + + // check if it's the old document + + if (this.document === document) return; + this.document = document; + + // check if we have done feature detection on this document before + + var root = document.documentElement, + rootUid = this.getUIDXML(root), + features = featuresCache[rootUid], + feature; + + if (features){ + for (feature in features){ + this[feature] = features[feature]; + } + return; + } + + features = featuresCache[rootUid] = {}; + + features.root = root; + features.isXMLDocument = this.isXML(document); + + features.brokenStarGEBTN + = features.starSelectsClosedQSA + = features.idGetsName + = features.brokenMixedCaseQSA + = features.brokenGEBCN + = features.brokenCheckedQSA + = features.brokenEmptyAttributeQSA + = features.isHTMLDocument + = features.nativeMatchesSelector + = false; + + var starSelectsClosed, starSelectsComments, + brokenSecondClassNameGEBCN, cachedGetElementsByClassName, + brokenFormAttributeGetter; + + var selected, id = 'slick_uniqueid'; + var testNode = document.createElement('div'); + + var testRoot = document.body || document.getElementsByTagName('body')[0] || root; + testRoot.appendChild(testNode); + + // on non-HTML documents innerHTML and getElementsById doesnt work properly + try { + testNode.innerHTML = '<a id="'+id+'"></a>'; + features.isHTMLDocument = !!document.getElementById(id); + } catch(e){}; + + if (features.isHTMLDocument){ + + testNode.style.display = 'none'; + + // IE returns comment nodes for getElementsByTagName('*') for some documents + testNode.appendChild(document.createComment('')); + starSelectsComments = (testNode.getElementsByTagName('*').length > 1); + + // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents + try { + testNode.innerHTML = 'foo</foo>'; + selected = testNode.getElementsByTagName('*'); + starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + features.brokenStarGEBTN = starSelectsComments || starSelectsClosed; + + // IE returns elements with the name instead of just id for getElementsById for some documents + try { + testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>'; + features.idGetsName = document.getElementById(id) === testNode.firstChild; + } catch(e){}; + + if (testNode.getElementsByClassName){ + + // Safari 3.2 getElementsByClassName caches results + try { + testNode.innerHTML = '<a class="f"></a><a class="b"></a>'; + testNode.getElementsByClassName('b').length; + testNode.firstChild.className = 'b'; + cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2); + } catch(e){}; + + // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one + try { + testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>'; + brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); + } catch(e){}; + + features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; + } + + if (testNode.querySelectorAll){ + // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents + try { + testNode.innerHTML = 'foo</foo>'; + selected = testNode.querySelectorAll('*'); + features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode + try { + testNode.innerHTML = '<a class="MiX"></a>'; + features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length; + } catch(e){}; + + // Webkit and Opera dont return selected options on querySelectorAll + try { + testNode.innerHTML = '<select><option selected="selected">a</option></select>'; + features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0); + } catch(e){}; + + // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll + try { + testNode.innerHTML = '<a class=""></a>'; + features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0); + } catch(e){}; + + } + + // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input + try { + testNode.innerHTML = '<form action="s"><input id="action"/></form>'; + brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's'); + } catch(e){}; + + // native matchesSelector function + + features.nativeMatchesSelector = root.matches || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector; + if (features.nativeMatchesSelector) try { + // if matchesSelector trows errors on incorrect sintaxes we can use it + features.nativeMatchesSelector.call(root, ':slick'); + features.nativeMatchesSelector = null; + } catch(e){}; + + } + + try { + root.slick_expando = 1; + delete root.slick_expando; + features.getUID = this.getUIDHTML; + } catch(e) { + features.getUID = this.getUIDXML; + } + + testRoot.removeChild(testNode); + testNode = selected = testRoot = null; + + // getAttribute + + features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){ + var method = this.attributeGetters[name]; + if (method) return method.call(node); + var attributeNode = node.getAttributeNode(name); + return (attributeNode) ? attributeNode.nodeValue : null; + } : function(node, name){ + var method = this.attributeGetters[name]; + return (method) ? method.call(node) : node.getAttribute(name); + }; + + // hasAttribute + + features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) { + return node.hasAttribute(attribute); + } : function(node, attribute) { + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }; + + // contains + // FIXME: Add specs: local.contains should be different for xml and html documents? + var nativeRootContains = root && this.isNativeCode(root.contains), + nativeDocumentContains = document && this.isNativeCode(document.contains); + + features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){ + return context.contains(node); + } : (nativeRootContains && !nativeDocumentContains) ? function(context, node){ + // IE8 does not have .contains on document. + return context === node || ((context === document) ? document.documentElement : context).contains(node); + } : (root && root.compareDocumentPosition) ? function(context, node){ + return context === node || !!(context.compareDocumentPosition(node) & 16); + } : function(context, node){ + if (node) do { + if (node === context) return true; + } while ((node = node.parentNode)); + return false; + }; + + // document order sorting + // credits to Sizzle (http://sizzlejs.com/) + + features.documentSorter = (root.compareDocumentPosition) ? function(a, b){ + if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0; + return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + } : ('sourceIndex' in root) ? function(a, b){ + if (!a.sourceIndex || !b.sourceIndex) return 0; + return a.sourceIndex - b.sourceIndex; + } : (document.createRange) ? function(a, b){ + if (!a.ownerDocument || !b.ownerDocument) return 0; + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + return aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + } : null ; + + root = null; + + for (feature in features){ + this[feature] = features[feature]; + } +}; + +// Main Method + +var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/, + reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/, + qsaFailExpCache = {}; + +local.search = function(context, expression, append, first){ + + var found = this.found = (first) ? null : (append || []); + + if (!context) return found; + else if (context.navigator) context = context.document; // Convert the node from a window to a document + else if (!context.nodeType) return found; + + // setup + + var parsed, i, + uniques = this.uniques = {}, + hasOthers = !!(append && append.length), + contextIsDocument = (context.nodeType == 9); + + if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context); + + // avoid duplicating items already in the append array + if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true; + + // expression checks + + if (typeof expression == 'string'){ // expression is a string + + /*<simple-selectors-override>*/ + var simpleSelector = expression.match(reSimpleSelector); + simpleSelectors: if (simpleSelector) { + + var symbol = simpleSelector[1], + name = simpleSelector[2], + node, nodes; + + if (!symbol){ + + if (name == '*' && this.brokenStarGEBTN) break simpleSelectors; + nodes = context.getElementsByTagName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + } else if (symbol == '#'){ + + if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors; + node = context.getElementById(name); + if (!node) return found; + if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors; + if (first) return node || null; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + + } else if (symbol == '.'){ + + if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors; + if (context.getElementsByClassName && !this.brokenGEBCN){ + nodes = context.getElementsByClassName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } else { + var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)'); + nodes = context.getElementsByTagName('*'); + for (i = 0; node = nodes[i++];){ + className = node.className; + if (!(className && matchClass.test(className))) continue; + if (first) return node; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } + + } + + if (hasOthers) this.sort(found); + return (first) ? null : found; + + } + /*</simple-selectors-override>*/ + + /*<query-selector-override>*/ + querySelector: if (context.querySelectorAll) { + + if (!this.isHTMLDocument + || qsaFailExpCache[expression] + //TODO: only skip when expression is actually mixed case + || this.brokenMixedCaseQSA + || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) + || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) + || (!contextIsDocument //Abort when !contextIsDocument and... + // there are multiple expressions in the selector + // since we currently only fix non-document rooted QSA for single expression selectors + && expression.indexOf(',') > -1 + ) + || Slick.disableQSA + ) break querySelector; + + var _expression = expression, _context = context; + if (!contextIsDocument){ + // non-document rooted QSA + // credits to Andrew Dupont + var currentId = _context.getAttribute('id'), slickid = 'slickid__'; + _context.setAttribute('id', slickid); + _expression = '#' + slickid + ' ' + _expression; + context = _context.parentNode; + } + + try { + if (first) return context.querySelector(_expression) || null; + else nodes = context.querySelectorAll(_expression); + } catch(e) { + qsaFailExpCache[expression] = 1; + break querySelector; + } finally { + if (!contextIsDocument){ + if (currentId) _context.setAttribute('id', currentId); + else _context.removeAttribute('id'); + context = _context; + } + } + + if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){ + if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node); + } else for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + if (hasOthers) this.sort(found); + return found; + + } + /*</query-selector-override>*/ + + parsed = this.Slick.parse(expression); + if (!parsed.length) return found; + } else if (expression == null){ // there is no expression + return found; + } else if (expression.Slick){ // expression is a parsed Slick object + parsed = expression; + } else if (this.contains(context.documentElement || context, expression)){ // expression is a node + (found) ? found.push(expression) : found = expression; + return found; + } else { // other junk + return found; + } + + /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ + + // cache elements for the nth selectors + + this.posNTH = {}; + this.posNTHLast = {}; + this.posNTHType = {}; + this.posNTHTypeLast = {}; + + /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ + + // if append is null and there is only a single selector with one expression use pushArray, else use pushUID + this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID; + + if (found == null) found = []; + + // default engine + + var j, m, n; + var combinator, tag, id, classList, classes, attributes, pseudos; + var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions; + + search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){ + + combinator = 'combinator:' + currentBit.combinator; + if (!this[combinator]) continue search; + + tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase(); + id = currentBit.id; + classList = currentBit.classList; + classes = currentBit.classes; + attributes = currentBit.attributes; + pseudos = currentBit.pseudos; + lastBit = (j === (currentExpression.length - 1)); + + this.bitUniques = {}; + + if (lastBit){ + this.uniques = uniques; + this.found = found; + } else { + this.uniques = {}; + this.found = []; + } + + if (j === 0){ + this[combinator](context, tag, id, classes, attributes, pseudos, classList); + if (first && lastBit && found.length) break search; + } else { + if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){ + this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + if (found.length) break search; + } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + } + + currentItems = this.found; + } + + // should sort if there are nodes in append and if you pass multiple expressions. + if (hasOthers || (parsed.expressions.length > 1)) this.sort(found); + + return (first) ? (found[0] || null) : found; +}; + +// Utils + +local.uidx = 1; +local.uidk = 'slick-uniqueid'; + +local.getUIDXML = function(node){ + var uid = node.getAttribute(this.uidk); + if (!uid){ + uid = this.uidx++; + node.setAttribute(this.uidk, uid); + } + return uid; +}; + +local.getUIDHTML = function(node){ + return node.uniqueNumber || (node.uniqueNumber = this.uidx++); +}; + +// sort based on the setDocument documentSorter method. + +local.sort = function(results){ + if (!this.documentSorter) return results; + results.sort(this.documentSorter); + return results; +}; + +/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ + +local.cacheNTH = {}; + +local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/; + +local.parseNTHArgument = function(argument){ + var parsed = argument.match(this.matchNTH); + if (!parsed) return false; + var special = parsed[2] || false; + var a = parsed[1] || 1; + if (a == '-') a = -1; + var b = +parsed[3] || 0; + parsed = + (special == 'n') ? {a: a, b: b} : + (special == 'odd') ? {a: 2, b: 1} : + (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a}; + + return (this.cacheNTH[argument] = parsed); +}; + +local.createNTHPseudo = function(child, sibling, positions, ofType){ + return function(node, argument){ + var uid = this.getUID(node); + if (!this[positions][uid]){ + var parent = node.parentNode; + if (!parent) return false; + var el = parent[child], count = 1; + if (ofType){ + var nodeName = node.nodeName; + do { + if (el.nodeName != nodeName) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } else { + do { + if (el.nodeType != 1) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } + } + argument = argument || 'n'; + var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument); + if (!parsed) return false; + var a = parsed.a, b = parsed.b, pos = this[positions][uid]; + if (a == 0) return b == pos; + if (a > 0){ + if (pos < b) return false; + } else { + if (b < pos) return false; + } + return ((pos - b) % a) == 0; + }; +}; + +/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ + +local.pushArray = function(node, tag, id, classes, attributes, pseudos){ + if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node); +}; + +local.pushUID = function(node, tag, id, classes, attributes, pseudos){ + var uid = this.getUID(node); + if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){ + this.uniques[uid] = true; + this.found.push(node); + } +}; + +local.matchNode = function(node, selector){ + if (this.isHTMLDocument && this.nativeMatchesSelector){ + try { + return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); + } catch(matchError) {} + } + + var parsed = this.Slick.parse(selector); + if (!parsed) return true; + + // simple (single) selectors + var expressions = parsed.expressions, simpleExpCounter = 0, i; + for (i = 0; (currentExpression = expressions[i]); i++){ + if (currentExpression.length == 1){ + var exp = currentExpression[0]; + if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; + simpleExpCounter++; + } + } + + if (simpleExpCounter == parsed.length) return false; + + var nodes = this.search(this.document, parsed), item; + for (i = 0; item = nodes[i++];){ + if (item === node) return true; + } + return false; +}; + +local.matchPseudo = function(node, name, argument){ + var pseudoName = 'pseudo:' + name; + if (this[pseudoName]) return this[pseudoName](node, argument); + var attribute = this.getAttribute(node, name); + return (argument) ? argument == attribute : !!attribute; +}; + +local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ + if (tag){ + var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase(); + if (tag == '*'){ + if (nodeName < '@') return false; // Fix for comment nodes and closed nodes + } else { + if (nodeName != tag) return false; + } + } + + if (id && node.getAttribute('id') != id) return false; + + var i, part, cls; + if (classes) for (i = classes.length; i--;){ + cls = this.getAttribute(node, 'class'); + if (!(cls && classes[i].regexp.test(cls))) return false; + } + if (attributes) for (i = attributes.length; i--;){ + part = attributes[i]; + if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false; + } + if (pseudos) for (i = pseudos.length; i--;){ + part = pseudos[i]; + if (!this.matchPseudo(node, part.key, part.value)) return false; + } + return true; +}; + +var combinators = { + + ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level + + var i, item, children; + + if (this.isHTMLDocument){ + getById: if (id){ + item = this.document.getElementById(id); + if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){ + // all[id] returns all the elements with that name or id inside node + // if theres just one it will return the element, else it will be a collection + children = node.all[id]; + if (!children) return; + if (!children[0]) children = [children]; + for (i = 0; item = children[i++];){ + var idNode = item.getAttributeNode('id'); + if (idNode && idNode.nodeValue == id){ + this.push(item, tag, null, classes, attributes, pseudos); + break; + } + } + return; + } + if (!item){ + // if the context is in the dom we return, else we will try GEBTN, breaking the getById label + if (this.contains(this.root, node)) return; + else break getById; + } else if (this.document !== node && !this.contains(node, item)) return; + this.push(item, tag, null, classes, attributes, pseudos); + return; + } + getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){ + children = node.getElementsByClassName(classList.join(' ')); + if (!(children && children.length)) break getByClass; + for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos); + return; + } + } + getByTag: { + children = node.getElementsByTagName(tag); + if (!(children && children.length)) break getByTag; + if (!this.brokenStarGEBTN) tag = null; + for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos); + } + }, + + '>': function(node, tag, id, classes, attributes, pseudos){ // direct children + if ((node = node.firstChild)) do { + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + } while ((node = node.nextSibling)); + }, + + '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling + while ((node = node.nextSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '^': function(node, tag, id, classes, attributes, pseudos){ // first child + node = node.firstChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings + while ((node = node.nextSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + }, + + '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling + this['combinator:+'](node, tag, id, classes, attributes, pseudos); + this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + }, + + '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings + this['combinator:~'](node, tag, id, classes, attributes, pseudos); + this['combinator:!~'](node, tag, id, classes, attributes, pseudos); + }, + + '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document + while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level) + node = node.parentNode; + if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling + while ((node = node.previousSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '!^': function(node, tag, id, classes, attributes, pseudos){ // last child + node = node.lastChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings + while ((node = node.previousSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + } + +}; + +for (var c in combinators) local['combinator:' + c] = combinators[c]; + +var pseudos = { + + /*<pseudo-selectors>*/ + + 'empty': function(node){ + var child = node.firstChild; + return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length; + }, + + 'not': function(node, expression){ + return !this.matchNode(node, expression); + }, + + 'contains': function(node, text){ + return (node.innerText || node.textContent || '').indexOf(text) > -1; + }, + + 'first-child': function(node){ + while ((node = node.previousSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'last-child': function(node){ + while ((node = node.nextSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'only-child': function(node){ + var prev = node; + while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeType == 1) return false; + return true; + }, + + /*<nth-pseudo-selectors>*/ + + 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'), + + 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'), + + 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true), + + 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), + + 'index': function(node, index){ + return this['pseudo:nth-child'](node, '' + (index + 1)); + }, + + 'even': function(node){ + return this['pseudo:nth-child'](node, '2n'); + }, + + 'odd': function(node){ + return this['pseudo:nth-child'](node, '2n+1'); + }, + + /*</nth-pseudo-selectors>*/ + + /*<of-type-pseudo-selectors>*/ + + 'first-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'last-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'only-of-type': function(node){ + var prev = node, nodeName = node.nodeName; + while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false; + return true; + }, + + /*</of-type-pseudo-selectors>*/ + + // custom pseudos + + 'enabled': function(node){ + return !node.disabled; + }, + + 'disabled': function(node){ + return node.disabled; + }, + + 'checked': function(node){ + return node.checked || node.selected; + }, + + 'focus': function(node){ + return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex')); + }, + + 'root': function(node){ + return (node === this.root); + }, + + 'selected': function(node){ + return node.selected; + } + + /*</pseudo-selectors>*/ +}; + +for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; + +// attributes methods + +var attributeGetters = local.attributeGetters = { + + 'for': function(){ + return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); + }, + + 'href': function(){ + return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href'); + }, + + 'style': function(){ + return (this.style) ? this.style.cssText : this.getAttribute('style'); + }, + + 'tabindex': function(){ + var attributeNode = this.getAttributeNode('tabindex'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; + }, + + 'type': function(){ + return this.getAttribute('type'); + }, + + 'maxlength': function(){ + var attributeNode = this.getAttributeNode('maxLength'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; + } + +}; + +attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength; + +// Slick + +var Slick = local.Slick = (this.Slick || {}); + +Slick.version = '1.1.7'; + +// Slick finder + +Slick.search = function(context, expression, append){ + return local.search(context, expression, append); +}; + +Slick.find = function(context, expression){ + return local.search(context, expression, null, true); +}; + +// Slick containment checker + +Slick.contains = function(container, node){ + local.setDocument(container); + return local.contains(container, node); +}; + +// Slick attribute getter + +Slick.getAttribute = function(node, name){ + local.setDocument(node); + return local.getAttribute(node, name); +}; + +Slick.hasAttribute = function(node, name){ + local.setDocument(node); + return local.hasAttribute(node, name); +}; + +// Slick matcher + +Slick.match = function(node, selector){ + if (!(node && selector)) return false; + if (!selector || selector === node) return true; + local.setDocument(node); + return local.matchNode(node, selector); +}; + +// Slick attribute accessor + +Slick.defineAttributeGetter = function(name, fn){ + local.attributeGetters[name] = fn; + return this; +}; + +Slick.lookupAttributeGetter = function(name){ + return local.attributeGetters[name]; +}; + +// Slick pseudo accessor + +Slick.definePseudo = function(name, fn){ + local['pseudo:' + name] = function(node, argument){ + return fn.call(node, argument); + }; + return this; +}; + +Slick.lookupPseudo = function(name){ + var pseudo = local['pseudo:' + name]; + if (pseudo) return function(argument){ + return pseudo.call(this, argument); + }; + return null; +}; + +// Slick overrides accessor + +Slick.override = function(regexp, fn){ + local.override(regexp, fn); + return this; +}; + +Slick.isXML = local.isXML; + +Slick.uidOf = function(node){ + return local.getUIDHTML(node); +}; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); + + +/* +--- + +name: Element + +description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. + +license: MIT-style license. + +requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder] + +provides: [Element, Elements, $, $$, IFrame, Selectors] + +... +*/ + +var Element = this.Element = function(tag, props){ + var konstructor = Element.Constructors[tag]; + if (konstructor) return konstructor(props); + if (typeof tag != 'string') return document.id(tag).set(props); + + if (!props) props = {}; + + if (!(/^[\w-]+$/).test(tag)){ + var parsed = Slick.parse(tag).expressions[0][0]; + tag = (parsed.tag == '*') ? 'div' : parsed.tag; + if (parsed.id && props.id == null) props.id = parsed.id; + + var attributes = parsed.attributes; + if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){ + attr = attributes[i]; + if (props[attr.key] != null) continue; + + if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; + else if (!attr.value && !attr.operator) props[attr.key] = true; + } + + if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); + } + + return document.newElement(tag, props); +}; + + +if (Browser.Element){ + Element.prototype = Browser.Element.prototype; + // IE8 and IE9 require the wrapping. + Element.prototype._fireEvent = (function(fireEvent){ + return function(type, event){ + return fireEvent.call(this, type, event); + }; + })(Element.prototype.fireEvent); +} + +new Type('Element', Element).mirror(function(name){ + if (Array.prototype[name]) return; + + var obj = {}; + obj[name] = function(){ + var results = [], args = arguments, elements = true; + for (var i = 0, l = this.length; i < l; i++){ + var element = this[i], result = results[i] = element[name].apply(element, args); + elements = (elements && typeOf(result) == 'element'); + } + return (elements) ? new Elements(results) : results; + }; + + Elements.implement(obj); +}); + +if (!Browser.Element){ + Element.parent = Object; + + Element.Prototype = { + '$constructor': Element, + '$family': Function.from('element').hide() + }; + + Element.mirror(function(name, method){ + Element.Prototype[name] = method; + }); +} + +Element.Constructors = {}; + + + +var IFrame = new Type('IFrame', function(){ + var params = Array.link(arguments, { + properties: Type.isObject, + iframe: function(obj){ + return (obj != null); + } + }); + + var props = params.properties || {}, iframe; + if (params.iframe) iframe = document.id(params.iframe); + var onload = props.onload || function(){}; + delete props.onload; + props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); + iframe = new Element(iframe || 'iframe', props); + + var onLoad = function(){ + onload.call(iframe.contentWindow); + }; + + if (window.frames[props.id]) onLoad(); + else iframe.addListener('load', onLoad); + return iframe; +}); + +var Elements = this.Elements = function(nodes){ + if (nodes && nodes.length){ + var uniques = {}, node; + for (var i = 0; node = nodes[i++];){ + var uid = Slick.uidOf(node); + if (!uniques[uid]){ + uniques[uid] = true; + this.push(node); + } + } + } +}; + +Elements.prototype = {length: 0}; +Elements.parent = Array; + +new Type('Elements', Elements).implement({ + + filter: function(filter, bind){ + if (!filter) return this; + return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ + return item.match(filter); + } : filter, bind)); + }.protect(), + + push: function(){ + var length = this.length; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) this[length++] = item; + } + return (this.length = length); + }.protect(), + + unshift: function(){ + var items = []; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) items.push(item); + } + return Array.prototype.unshift.apply(this, items); + }.protect(), + + concat: function(){ + var newElements = new Elements(this); + for (var i = 0, l = arguments.length; i < l; i++){ + var item = arguments[i]; + if (Type.isEnumerable(item)) newElements.append(item); + else newElements.push(item); + } + return newElements; + }.protect(), + + append: function(collection){ + for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); + return this; + }.protect(), + + empty: function(){ + while (this.length) delete this[--this.length]; + return this; + }.protect() + +}); + + + +(function(){ + +// FF, IE +var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; + +splice.call(object, 1, 1); +if (object[1] == 1) Elements.implement('splice', function(){ + var length = this.length; + var result = splice.apply(this, arguments); + while (length >= this.length) delete this[length--]; + return result; +}.protect()); + +Array.forEachMethod(function(method, name){ + Elements.implement(name, method); +}); + +Array.mirror(Elements); + +/*<ltIE8>*/ +var createElementAcceptsHTML; +try { + createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x'); +} catch (e){} + +var escapeQuotes = function(html){ + return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); +}; +/*</ltIE8>*/ + +Document.implement({ + + newElement: function(tag, props){ + if (props && props.checked != null) props.defaultChecked = props.checked; + /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8 + if (createElementAcceptsHTML && props){ + tag = '<' + tag; + if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; + if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; + tag += '>'; + delete props.name; + delete props.type; + } + /*</ltIE8>*/ + return this.id(this.createElement(tag)).set(props); + } + +}); + +})(); + +(function(){ + +Slick.uidOf(window); +Slick.uidOf(document); + +Document.implement({ + + newTextNode: function(text){ + return this.createTextNode(text); + }, + + getDocument: function(){ + return this; + }, + + getWindow: function(){ + return this.window; + }, + + id: (function(){ + + var types = { + + string: function(id, nocash, doc){ + id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); + return (id) ? types.element(id, nocash) : null; + }, + + element: function(el, nocash){ + Slick.uidOf(el); + if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ + var fireEvent = el.fireEvent; + // wrapping needed in IE7, or else crash + el._fireEvent = function(type, event){ + return fireEvent(type, event); + }; + Object.append(el, Element.Prototype); + } + return el; + }, + + object: function(obj, nocash, doc){ + if (obj.toElement) return types.element(obj.toElement(doc), nocash); + return null; + } + + }; + + types.textnode = types.whitespace = types.window = types.document = function(zero){ + return zero; + }; + + return function(el, nocash, doc){ + if (el && el.$family && el.uniqueNumber) return el; + var type = typeOf(el); + return (types[type]) ? types[type](el, nocash, doc || document) : null; + }; + + })() + +}); + +if (window.$ == null) Window.implement('$', function(el, nc){ + return document.id(el, nc, this.document); +}); + +Window.implement({ + + getDocument: function(){ + return this.document; + }, + + getWindow: function(){ + return this; + } + +}); + +[Document, Element].invoke('implement', { + + getElements: function(expression){ + return Slick.search(this, expression, new Elements); + }, + + getElement: function(expression){ + return document.id(Slick.find(this, expression)); + } + +}); + +var contains = {contains: function(element){ + return Slick.contains(this, element); +}}; + +if (!document.contains) Document.implement(contains); +if (!document.createElement('div').contains) Element.implement(contains); + + + +// tree walking + +var injectCombinator = function(expression, combinator){ + if (!expression) return combinator; + + expression = Object.clone(Slick.parse(expression)); + + var expressions = expression.expressions; + for (var i = expressions.length; i--;) + expressions[i][0].combinator = combinator; + + return expression; +}; + +Object.forEach({ + getNext: '~', + getPrevious: '!~', + getParent: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElement(injectCombinator(expression, combinator)); + }); +}); + +Object.forEach({ + getAllNext: '~', + getAllPrevious: '!~', + getSiblings: '~~', + getChildren: '>', + getParents: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElements(injectCombinator(expression, combinator)); + }); +}); + +Element.implement({ + + getFirst: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); + }, + + getLast: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); + }, + + getWindow: function(){ + return this.ownerDocument.window; + }, + + getDocument: function(){ + return this.ownerDocument; + }, + + getElementById: function(id){ + return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); + }, + + match: function(expression){ + return !expression || Slick.match(this, expression); + } + +}); + + + +if (window.$$ == null) Window.implement('$$', function(selector){ + if (arguments.length == 1){ + if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); + else if (Type.isEnumerable(selector)) return new Elements(selector); + } + return new Elements(arguments); +}); + +// Inserters + +var inserters = { + + before: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element); + }, + + after: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element.nextSibling); + }, + + bottom: function(context, element){ + element.appendChild(context); + }, + + top: function(context, element){ + element.insertBefore(context, element.firstChild); + } + +}; + +inserters.inside = inserters.bottom; + + + +// getProperty / setProperty + +var propertyGetters = {}, propertySetters = {}; + +// properties + +var properties = {}; +Array.forEach([ + 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', + 'frameBorder', 'rowSpan', 'tabIndex', 'useMap' +], function(property){ + properties[property.toLowerCase()] = property; +}); + +properties.html = 'innerHTML'; +properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent'; + +Object.forEach(properties, function(real, key){ + propertySetters[key] = function(node, value){ + node[real] = value; + }; + propertyGetters[key] = function(node){ + return node[real]; + }; +}); + +// Booleans + +var bools = [ + 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', + 'disabled', 'readOnly', 'multiple', 'selected', 'noresize', + 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay', + 'loop' +]; + +var booleans = {}; +Array.forEach(bools, function(bool){ + var lower = bool.toLowerCase(); + booleans[lower] = bool; + propertySetters[lower] = function(node, value){ + node[bool] = !!value; + }; + propertyGetters[lower] = function(node){ + return !!node[bool]; + }; +}); + +// Special cases + +Object.append(propertySetters, { + + 'class': function(node, value){ + ('className' in node) ? node.className = (value || '') : node.setAttribute('class', value); + }, + + 'for': function(node, value){ + ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value); + }, + + 'style': function(node, value){ + (node.style) ? node.style.cssText = value : node.setAttribute('style', value); + }, + + 'value': function(node, value){ + node.value = (value != null) ? value : ''; + } + +}); + +propertyGetters['class'] = function(node){ + return ('className' in node) ? node.className || null : node.getAttribute('class'); +}; + +/* <webkit> */ +var el = document.createElement('button'); +// IE sets type as readonly and throws +try { el.type = 'button'; } catch(e){} +if (el.type != 'button') propertySetters.type = function(node, value){ + node.setAttribute('type', value); +}; +el = null; +/* </webkit> */ + +/*<IE>*/ +var input = document.createElement('input'); +input.value = 't'; +input.type = 'submit'; +if (input.value != 't') propertySetters.type = function(node, type){ + var value = node.value; + node.type = type; + node.value = value; +}; +input = null; +/*</IE>*/ + +/* getProperty, setProperty */ + +/* <ltIE9> */ +var pollutesGetAttribute = (function(div){ + div.random = 'attribute'; + return (div.getAttribute('random') == 'attribute'); +})(document.createElement('div')); + +var hasCloneBug = (function(test){ + test.innerHTML = '<object><param name="should_fix" value="the unknown"></object>'; + return test.cloneNode(true).firstChild.childNodes.length != 1; +})(document.createElement('div')); +/* </ltIE9> */ + +var hasClassList = !!document.createElement('div').classList; + +var classes = function(className){ + var classNames = (className || '').clean().split(" "), uniques = {}; + return classNames.filter(function(className){ + if (className !== "" && !uniques[className]) return uniques[className] = className; + }); +}; + +var addToClassList = function(name){ + this.classList.add(name); +}; + +var removeFromClassList = function(name){ + this.classList.remove(name); +}; + +Element.implement({ + + setProperty: function(name, value){ + var setter = propertySetters[name.toLowerCase()]; + if (setter){ + setter(this, value); + } else { + /* <ltIE9> */ + var attributeWhiteList; + if (pollutesGetAttribute) attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + /* </ltIE9> */ + + if (value == null){ + this.removeAttribute(name); + /* <ltIE9> */ + if (pollutesGetAttribute) delete attributeWhiteList[name]; + /* </ltIE9> */ + } else { + this.setAttribute(name, '' + value); + /* <ltIE9> */ + if (pollutesGetAttribute) attributeWhiteList[name] = true; + /* </ltIE9> */ + } + } + return this; + }, + + setProperties: function(attributes){ + for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); + return this; + }, + + getProperty: function(name){ + var getter = propertyGetters[name.toLowerCase()]; + if (getter) return getter(this); + /* <ltIE9> */ + if (pollutesGetAttribute){ + var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + if (!attr) return null; + if (attr.expando && !attributeWhiteList[name]){ + var outer = this.outerHTML; + // segment by the opening tag and find mention of attribute name + if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null; + attributeWhiteList[name] = true; + } + } + /* </ltIE9> */ + var result = Slick.getAttribute(this, name); + return (!result && !Slick.hasAttribute(this, name)) ? null : result; + }, + + getProperties: function(){ + var args = Array.from(arguments); + return args.map(this.getProperty, this).associate(args); + }, + + removeProperty: function(name){ + return this.setProperty(name, null); + }, + + removeProperties: function(){ + Array.each(arguments, this.removeProperty, this); + return this; + }, + + set: function(prop, value){ + var property = Element.Properties[prop]; + (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); + }.overloadSetter(), + + get: function(prop){ + var property = Element.Properties[prop]; + return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); + }.overloadGetter(), + + erase: function(prop){ + var property = Element.Properties[prop]; + (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); + return this; + }, + + hasClass: hasClassList ? function(className){ + return this.classList.contains(className); + } : function(className){ + return this.className.clean().contains(className, ' '); + }, + + addClass: hasClassList ? function(className){ + classes(className).forEach(addToClassList, this); + return this; + } : function(className){ + this.className = classes(className + ' ' + this.className).join(' '); + return this; + }, + + removeClass: hasClassList ? function(className){ + classes(className).forEach(removeFromClassList, this); + return this; + } : function(className){ + var classNames = classes(this.className); + classes(className).forEach(classNames.erase, classNames); + this.className = classNames.join(' '); + return this; + }, + + toggleClass: function(className, force){ + if (force == null) force = !this.hasClass(className); + return (force) ? this.addClass(className) : this.removeClass(className); + }, + + adopt: function(){ + var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; + if (length > 1) parent = fragment = document.createDocumentFragment(); + + for (var i = 0; i < length; i++){ + var element = document.id(elements[i], true); + if (element) parent.appendChild(element); + } + + if (fragment) this.appendChild(fragment); + + return this; + }, + + appendText: function(text, where){ + return this.grab(this.getDocument().newTextNode(text), where); + }, + + grab: function(el, where){ + inserters[where || 'bottom'](document.id(el, true), this); + return this; + }, + + inject: function(el, where){ + inserters[where || 'bottom'](this, document.id(el, true)); + return this; + }, + + replaces: function(el){ + el = document.id(el, true); + el.parentNode.replaceChild(this, el); + return this; + }, + + wraps: function(el, where){ + el = document.id(el, true); + return this.replaces(el).grab(el, where); + }, + + getSelected: function(){ + this.selectedIndex; // Safari 3.2.1 + return new Elements(Array.from(this.options).filter(function(option){ + return option.selected; + })); + }, + + toQueryString: function(){ + var queryString = []; + this.getElements('input, select, textarea').each(function(el){ + var type = el.type; + if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; + + var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ + // IE + return document.id(opt).get('value'); + }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); + + Array.from(value).each(function(val){ + if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); + }); + }); + return queryString.join('&'); + } + +}); + + +// appendHTML + +var appendInserters = { + before: 'beforeBegin', + after: 'afterEnd', + bottom: 'beforeEnd', + top: 'afterBegin', + inside: 'beforeEnd' +}; + +Element.implement('appendHTML', ('insertAdjacentHTML' in document.createElement('div')) ? function(html, where){ + this.insertAdjacentHTML(appendInserters[where || 'bottom'], html); + return this; +} : function(html, where){ + var temp = new Element('div', {html: html}), + children = temp.childNodes, + fragment = temp.firstChild; + + if (!fragment) return this; + if (children.length > 1){ + fragment = document.createDocumentFragment(); + for (var i = 0, l = children.length; i < l; i++){ + fragment.appendChild(children[i]); + } + } + + inserters[where || 'bottom'](fragment, this); + return this; +}); + +var collected = {}, storage = {}; + +var get = function(uid){ + return (storage[uid] || (storage[uid] = {})); +}; + +var clean = function(item){ + var uid = item.uniqueNumber; + if (item.removeEvents) item.removeEvents(); + if (item.clearAttributes) item.clearAttributes(); + if (uid != null){ + delete collected[uid]; + delete storage[uid]; + } + return item; +}; + +var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; + +Element.implement({ + + destroy: function(){ + var children = clean(this).getElementsByTagName('*'); + Array.each(children, clean); + Element.dispose(this); + return null; + }, + + empty: function(){ + Array.from(this.childNodes).each(Element.dispose); + return this; + }, + + dispose: function(){ + return (this.parentNode) ? this.parentNode.removeChild(this) : this; + }, + + clone: function(contents, keepid){ + contents = contents !== false; + var clone = this.cloneNode(contents), ce = [clone], te = [this], i; + + if (contents){ + ce.append(Array.from(clone.getElementsByTagName('*'))); + te.append(Array.from(this.getElementsByTagName('*'))); + } + + for (i = ce.length; i--;){ + var node = ce[i], element = te[i]; + if (!keepid) node.removeAttribute('id'); + /*<ltIE9>*/ + if (node.clearAttributes){ + node.clearAttributes(); + node.mergeAttributes(element); + node.removeAttribute('uniqueNumber'); + if (node.options){ + var no = node.options, eo = element.options; + for (var j = no.length; j--;) no[j].selected = eo[j].selected; + } + } + /*</ltIE9>*/ + var prop = formProps[element.tagName.toLowerCase()]; + if (prop && element[prop]) node[prop] = element[prop]; + } + + /*<ltIE9>*/ + if (hasCloneBug){ + var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); + for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; + } + /*</ltIE9>*/ + return document.id(clone); + } + +}); + +[Element, Window, Document].invoke('implement', { + + addListener: function(type, fn){ + if (window.attachEvent && !window.addEventListener){ + collected[Slick.uidOf(this)] = this; + } + if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); + else this.attachEvent('on' + type, fn); + return this; + }, + + removeListener: function(type, fn){ + if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); + else this.detachEvent('on' + type, fn); + return this; + }, + + retrieve: function(property, dflt){ + var storage = get(Slick.uidOf(this)), prop = storage[property]; + if (dflt != null && prop == null) prop = storage[property] = dflt; + return prop != null ? prop : null; + }, + + store: function(property, value){ + var storage = get(Slick.uidOf(this)); + storage[property] = value; + return this; + }, + + eliminate: function(property){ + var storage = get(Slick.uidOf(this)); + delete storage[property]; + return this; + } + +}); + +/*<ltIE9>*/ +if (window.attachEvent && !window.addEventListener){ + var gc = function(){ + Object.each(collected, clean); + if (window.CollectGarbage) CollectGarbage(); + window.removeListener('unload', gc); + } + window.addListener('unload', gc); +} +/*</ltIE9>*/ + +Element.Properties = {}; + + + +Element.Properties.style = { + + set: function(style){ + this.style.cssText = style; + }, + + get: function(){ + return this.style.cssText; + }, + + erase: function(){ + this.style.cssText = ''; + } + +}; + +Element.Properties.tag = { + + get: function(){ + return this.tagName.toLowerCase(); + } + +}; + +Element.Properties.html = { + + set: function(html){ + if (html == null) html = ''; + else if (typeOf(html) == 'array') html = html.join(''); + this.innerHTML = html; + }, + + erase: function(){ + this.innerHTML = ''; + } + +}; + +var supportsHTML5Elements = true, supportsTableInnerHTML = true, supportsTRInnerHTML = true; + +/*<ltIE9>*/ +// technique by jdbarlett - http://jdbartlett.com/innershiv/ +var div = document.createElement('div'); +div.innerHTML = '<nav></nav>'; +supportsHTML5Elements = (div.childNodes.length == 1); +if (!supportsHTML5Elements){ + var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), + fragment = document.createDocumentFragment(), l = tags.length; + while (l--) fragment.createElement(tags[l]); +} +div = null; +/*</ltIE9>*/ + +/*<IE>*/ +supportsTableInnerHTML = Function.attempt(function(){ + var table = document.createElement('table'); + table.innerHTML = '<tr><td></td></tr>'; + return true; +}); + +/*<ltFF4>*/ +var tr = document.createElement('tr'), html = '<td></td>'; +tr.innerHTML = html; +supportsTRInnerHTML = (tr.innerHTML == html); +tr = null; +/*</ltFF4>*/ + +if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){ + + Element.Properties.html.set = (function(set){ + + var translations = { + table: [1, '<table>', '</table>'], + select: [1, '<select>', '</select>'], + tbody: [2, '<table><tbody>', '</tbody></table>'], + tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] + }; + + translations.thead = translations.tfoot = translations.tbody; + + return function(html){ + var wrap = translations[this.get('tag')]; + if (!wrap && !supportsHTML5Elements) wrap = [0, '', '']; + if (!wrap) return set.call(this, html); + + var level = wrap[0], wrapper = document.createElement('div'), target = wrapper; + if (!supportsHTML5Elements) fragment.appendChild(wrapper); + wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join(''); + while (level--) target = target.firstChild; + this.empty().adopt(target.childNodes); + if (!supportsHTML5Elements) fragment.removeChild(wrapper); + wrapper = null; + }; + + })(Element.Properties.html.set); +} +/*</IE>*/ + +/*<ltIE9>*/ +var testForm = document.createElement('form'); +testForm.innerHTML = '<select><option>s</option></select>'; + +if (testForm.firstChild.value != 's') Element.Properties.value = { + + set: function(value){ + var tag = this.get('tag'); + if (tag != 'select') return this.setProperty('value', value); + var options = this.getElements('option'); + value = String(value); + for (var i = 0; i < options.length; i++){ + var option = options[i], + attr = option.getAttributeNode('value'), + optionValue = (attr && attr.specified) ? option.value : option.get('text'); + if (optionValue === value) return option.selected = true; + } + }, + + get: function(){ + var option = this, tag = option.get('tag'); + + if (tag != 'select' && tag != 'option') return this.getProperty('value'); + + if (tag == 'select' && !(option = option.getSelected()[0])) return ''; + + var attr = option.getAttributeNode('value'); + return (attr && attr.specified) ? option.value : option.get('text'); + } + +}; +testForm = null; +/*</ltIE9>*/ + +/*<IE>*/ +if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = { + set: function(id){ + this.id = this.getAttributeNode('id').value = id; + }, + get: function(){ + return this.id || null; + }, + erase: function(){ + this.id = this.getAttributeNode('id').value = ''; + } +}; +/*</IE>*/ + +})(); + + +/* +--- + +name: Element.Style + +description: Contains methods for interacting with the styles of Elements in a fashionable way. + +license: MIT-style license. + +requires: Element + +provides: Element.Style + +... +*/ + +(function(){ + +var html = document.html, el; + +//<ltIE9> +// Check for oldIE, which does not remove styles when they're set to null +el = document.createElement('div'); +el.style.color = 'red'; +el.style.color = null; +var doesNotRemoveStyles = el.style.color == 'red'; + +// check for oldIE, which returns border* shorthand styles in the wrong order (color-width-style instead of width-style-color) +var border = '1px solid #123abc'; +el.style.border = border; +var returnsBordersInWrongOrder = el.style.border != border; +el = null; +//</ltIE9> + +var hasGetComputedStyle = !!window.getComputedStyle; + +Element.Properties.styles = {set: function(styles){ + this.setStyles(styles); +}}; + +var hasOpacity = (html.style.opacity != null), + hasFilter = (html.style.filter != null), + reAlpha = /alpha\(opacity=([\d.]+)\)/i; + +var setVisibility = function(element, opacity){ + element.store('$opacity', opacity); + element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden'; +}; + +//<ltIE9> +var setFilter = function(element, regexp, value){ + var style = element.style, + filter = style.filter || element.getComputedStyle('filter') || ''; + style.filter = (regexp.test(filter) ? filter.replace(regexp, value) : filter + ' ' + value).trim(); + if (!style.filter) style.removeAttribute('filter'); +}; +//</ltIE9> + +var setOpacity = (hasOpacity ? function(element, opacity){ + element.style.opacity = opacity; +} : (hasFilter ? function(element, opacity){ + if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; + if (opacity == null || opacity == 1){ + setFilter(element, reAlpha, ''); + if (opacity == 1 && getOpacity(element) != 1) setFilter(element, reAlpha, 'alpha(opacity=100)'); + } else { + setFilter(element, reAlpha, 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')'); + } +} : setVisibility)); + +var getOpacity = (hasOpacity ? function(element){ + var opacity = element.style.opacity || element.getComputedStyle('opacity'); + return (opacity == '') ? 1 : opacity.toFloat(); +} : (hasFilter ? function(element){ + var filter = (element.style.filter || element.getComputedStyle('filter')), + opacity; + if (filter) opacity = filter.match(reAlpha); + return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); +} : function(element){ + var opacity = element.retrieve('$opacity'); + if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1); + return opacity; +})); + +var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat', + namedPositions = {left: '0%', top: '0%', center: '50%', right: '100%', bottom: '100%'}, + hasBackgroundPositionXY = (html.style.backgroundPositionX != null); + +//<ltIE9> +var removeStyle = function(style, property){ + if (property == 'backgroundPosition'){ + style.removeAttribute(property + 'X'); + property += 'Y'; + } + style.removeAttribute(property); +}; +//</ltIE9> + +Element.implement({ + + getComputedStyle: function(property){ + if (!hasGetComputedStyle && this.currentStyle) return this.currentStyle[property.camelCase()]; + var defaultView = Element.getDocument(this).defaultView, + computed = defaultView ? defaultView.getComputedStyle(this, null) : null; + return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : ''; + }, + + setStyle: function(property, value){ + if (property == 'opacity'){ + if (value != null) value = parseFloat(value); + setOpacity(this, value); + return this; + } + property = (property == 'float' ? floatName : property).camelCase(); + if (typeOf(value) != 'string'){ + var map = (Element.Styles[property] || '@').split(' '); + value = Array.from(value).map(function(val, i){ + if (!map[i]) return ''; + return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; + }).join(' '); + } else if (value == String(Number(value))){ + value = Math.round(value); + } + this.style[property] = value; + //<ltIE9> + if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){ + removeStyle(this.style, property); + } + //</ltIE9> + return this; + }, + + getStyle: function(property){ + if (property == 'opacity') return getOpacity(this); + property = (property == 'float' ? floatName : property).camelCase(); + var result = this.style[property]; + if (!result || property == 'zIndex'){ + if (Element.ShortStyles.hasOwnProperty(property)){ + result = []; + for (var s in Element.ShortStyles[property]) result.push(this.getStyle(s)); + return result.join(' '); + } + result = this.getComputedStyle(property); + } + if (hasBackgroundPositionXY && /^backgroundPosition[XY]?$/.test(property)){ + return result.replace(/(top|right|bottom|left)/g, function(position){ + return namedPositions[position]; + }) || '0px'; + } + if (!result && property == 'backgroundPosition') return '0px 0px'; + if (result){ + result = String(result); + var color = result.match(/rgba?\([\d\s,]+\)/); + if (color) result = result.replace(color[0], color[0].rgbToHex()); + } + if (!hasGetComputedStyle && !this.style[property]){ + if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){ + var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; + values.each(function(value){ + size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); + }, this); + return this['offset' + property.capitalize()] - size + 'px'; + } + if ((/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){ + return '0px'; + } + } + //<ltIE9> + if (returnsBordersInWrongOrder && /^border(Top|Right|Bottom|Left)?$/.test(property) && /^#/.test(result)){ + return result.replace(/^(.+)\s(.+)\s(.+)$/, '$2 $3 $1'); + } + //</ltIE9> + return result; + }, + + setStyles: function(styles){ + for (var style in styles) this.setStyle(style, styles[style]); + return this; + }, + + getStyles: function(){ + var result = {}; + Array.flatten(arguments).each(function(key){ + result[key] = this.getStyle(key); + }, this); + return result; + } + +}); + +Element.Styles = { + left: '@px', top: '@px', bottom: '@px', right: '@px', + width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', + backgroundColor: 'rgb(@, @, @)', backgroundSize: '@px', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', + fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', + margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', + borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', + zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' +}; + + + + + +Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; + +['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ + var Short = Element.ShortStyles; + var All = Element.Styles; + ['margin', 'padding'].each(function(style){ + var sd = style + direction; + Short[style][sd] = All[sd] = '@px'; + }); + var bd = 'border' + direction; + Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; + var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; + Short[bd] = {}; + Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; + Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; + Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; +}); + +if (hasBackgroundPositionXY) Element.ShortStyles.backgroundPosition = {backgroundPositionX: '@', backgroundPositionY: '@'}; +})(); + + +/* +--- + +name: Element.Event + +description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary. + +license: MIT-style license. + +requires: [Element, Event] + +provides: Element.Event + +... +*/ + +(function(){ + +Element.Properties.events = {set: function(events){ + this.addEvents(events); +}}; + +[Element, Window, Document].invoke('implement', { + + addEvent: function(type, fn){ + var events = this.retrieve('events', {}); + if (!events[type]) events[type] = {keys: [], values: []}; + if (events[type].keys.contains(fn)) return this; + events[type].keys.push(fn); + var realType = type, + custom = Element.Events[type], + condition = fn, + self = this; + if (custom){ + if (custom.onAdd) custom.onAdd.call(this, fn, type); + if (custom.condition){ + condition = function(event){ + if (custom.condition.call(this, event, type)) return fn.call(this, event); + return true; + }; + } + if (custom.base) realType = Function.from(custom.base).call(this, type); + } + var defn = function(){ + return fn.call(self); + }; + var nativeEvent = Element.NativeEvents[realType]; + if (nativeEvent){ + if (nativeEvent == 2){ + defn = function(event){ + event = new DOMEvent(event, self.getWindow()); + if (condition.call(self, event) === false) event.stop(); + }; + } + this.addListener(realType, defn, arguments[2]); + } + events[type].values.push(defn); + return this; + }, + + removeEvent: function(type, fn){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + var list = events[type]; + var index = list.keys.indexOf(fn); + if (index == -1) return this; + var value = list.values[index]; + delete list.keys[index]; + delete list.values[index]; + var custom = Element.Events[type]; + if (custom){ + if (custom.onRemove) custom.onRemove.call(this, fn, type); + if (custom.base) type = Function.from(custom.base).call(this, type); + } + return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; + }, + + addEvents: function(events){ + for (var event in events) this.addEvent(event, events[event]); + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + var attached = this.retrieve('events'); + if (!attached) return this; + if (!events){ + for (type in attached) this.removeEvents(type); + this.eliminate('events'); + } else if (attached[events]){ + attached[events].keys.each(function(fn){ + this.removeEvent(events, fn); + }, this); + delete attached[events]; + } + return this; + }, + + fireEvent: function(type, args, delay){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + args = Array.from(args); + + events[type].keys.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + cloneEvents: function(from, type){ + from = document.id(from); + var events = from.retrieve('events'); + if (!events) return this; + if (!type){ + for (var eventType in events) this.cloneEvents(from, eventType); + } else if (events[type]){ + events[type].keys.each(function(fn){ + this.addEvent(type, fn); + }, this); + } + return this; + } + +}); + +Element.NativeEvents = { + click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons + mousewheel: 2, DOMMouseScroll: 2, //mouse wheel + mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement + keydown: 2, keypress: 2, keyup: 2, //keyboard + orientationchange: 2, // mobile + touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch + gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture + focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements + load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window + hashchange: 1, popstate: 2, // history + error: 1, abort: 1, scroll: 1 //misc +}; + +Element.Events = { + mousewheel: { + base: 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll' + } +}; + +var check = function(event){ + var related = event.relatedTarget; + if (related == null) return true; + if (!related) return false; + return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related)); +}; + +if ('onmouseenter' in document.documentElement){ + Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2; + Element.MouseenterCheck = check; +} else { + Element.Events.mouseenter = { + base: 'mouseover', + condition: check + }; + + Element.Events.mouseleave = { + base: 'mouseout', + condition: check + }; +} + +/*<ltIE9>*/ +if (!window.addEventListener){ + Element.NativeEvents.propertychange = 2; + Element.Events.change = { + base: function(){ + var type = this.type; + return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change'; + }, + condition: function(event){ + return event.type != 'propertychange' || event.event.propertyName == 'checked'; + } + }; +} +/*</ltIE9>*/ + + + +})(); + + +/* +--- + +name: Element.Delegation + +description: Extends the Element native object to include the delegate method for more efficient event management. + +license: MIT-style license. + +requires: [Element.Event] + +provides: [Element.Delegation] + +... +*/ + +(function(){ + +var eventListenerSupport = !!window.addEventListener; + +Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2; + +var bubbleUp = function(self, match, fn, event, target){ + while (target && target != self){ + if (match(target, event)) return fn.call(target, event, target); + target = document.id(target.parentNode); + } +}; + +var map = { + mouseenter: { + base: 'mouseover', + condition: Element.MouseenterCheck + }, + mouseleave: { + base: 'mouseout', + condition: Element.MouseenterCheck + }, + focus: { + base: 'focus' + (eventListenerSupport ? '' : 'in'), + capture: true + }, + blur: { + base: eventListenerSupport ? 'blur' : 'focusout', + capture: true + } +}; + +/*<ltIE9>*/ +var _key = '$delegation:'; +var formObserver = function(type){ + + return { + + base: 'focusin', + + remove: function(self, uid){ + var list = self.retrieve(_key + type + 'listeners', {})[uid]; + if (list && list.forms) for (var i = list.forms.length; i--;){ + list.forms[i].removeEvent(type, list.fns[i]); + } + }, + + listen: function(self, match, fn, event, target, uid){ + var form = (target.get('tag') == 'form') ? target : event.target.getParent('form'); + if (!form) return; + + var listeners = self.retrieve(_key + type + 'listeners', {}), + listener = listeners[uid] || {forms: [], fns: []}, + forms = listener.forms, fns = listener.fns; + + if (forms.indexOf(form) != -1) return; + forms.push(form); + + var _fn = function(event){ + bubbleUp(self, match, fn, event, target); + }; + form.addEvent(type, _fn); + fns.push(_fn); + + listeners[uid] = listener; + self.store(_key + type + 'listeners', listeners); + } + }; +}; + +var inputObserver = function(type){ + return { + base: 'focusin', + listen: function(self, match, fn, event, target){ + var events = {blur: function(){ + this.removeEvents(events); + }}; + events[type] = function(event){ + bubbleUp(self, match, fn, event, target); + }; + event.target.addEvents(events); + } + }; +}; + +if (!eventListenerSupport) Object.append(map, { + submit: formObserver('submit'), + reset: formObserver('reset'), + change: inputObserver('change'), + select: inputObserver('select') +}); +/*</ltIE9>*/ + +var proto = Element.prototype, + addEvent = proto.addEvent, + removeEvent = proto.removeEvent; + +var relay = function(old, method){ + return function(type, fn, useCapture){ + if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture); + var parsed = Slick.parse(type).expressions[0][0]; + if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture); + var newType = parsed.tag; + parsed.pseudos.slice(1).each(function(pseudo){ + newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : ''); + }); + old.call(this, type, fn); + return method.call(this, newType, parsed.pseudos[0].value, fn); + }; +}; + +var delegation = { + + addEvent: function(type, match, fn){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (stored) for (var _uid in stored){ + if (stored[_uid].fn == fn && stored[_uid].match == match) return this; + } + + var _type = type, _match = match, _fn = fn, _map = map[type] || {}; + type = _map.base || _type; + + match = function(target){ + return Slick.match(target, _match); + }; + + var elementEvent = Element.Events[_type]; + if (_map.condition || elementEvent && elementEvent.condition){ + var __match = match, condition = _map.condition || elementEvent.condition; + match = function(target, event){ + return __match(target, event) && condition.call(target, event, type); + }; + } + + var self = this, uid = String.uniqueID(); + var delegator = _map.listen ? function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) _map.listen(self, match, fn, event, target, uid); + } : function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) bubbleUp(self, match, fn, event, target); + }; + + if (!stored) stored = {}; + stored[uid] = { + match: _match, + fn: _fn, + delegator: delegator + }; + storage[_type] = stored; + return addEvent.call(this, type, delegator, _map.capture); + }, + + removeEvent: function(type, match, fn, _uid){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (!stored) return this; + + if (_uid){ + var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {}; + type = _map.base || _type; + if (_map.remove) _map.remove(this, _uid); + delete stored[_uid]; + storage[_type] = stored; + return removeEvent.call(this, type, delegator, _map.capture); + } + + var __uid, s; + if (fn) for (__uid in stored){ + s = stored[__uid]; + if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid); + } else for (__uid in stored){ + s = stored[__uid]; + if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid); + } + return this; + } + +}; + +[Element, Window, Document].invoke('implement', { + addEvent: relay(addEvent, delegation.addEvent), + removeEvent: relay(removeEvent, delegation.removeEvent) +}); + +})(); + + +/* +--- + +name: Element.Dimensions + +description: Contains methods to work with size, scroll, or positioning of Elements and the window object. + +license: MIT-style license. + +credits: + - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). + - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). + +requires: [Element, Element.Style] + +provides: [Element.Dimensions] + +... +*/ + +(function(){ + +var element = document.createElement('div'), + child = document.createElement('div'); +element.style.height = '0'; +element.appendChild(child); +var brokenOffsetParent = (child.offsetParent === element); +element = child = null; + +var isOffset = function(el){ + return styleString(el, 'position') != 'static' || isBody(el); +}; + +var isOffsetStatic = function(el){ + return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName); +}; + +Element.implement({ + + scrollTo: function(x, y){ + if (isBody(this)){ + this.getWindow().scrollTo(x, y); + } else { + this.scrollLeft = x; + this.scrollTop = y; + } + return this; + }, + + getSize: function(){ + if (isBody(this)) return this.getWindow().getSize(); + return {x: this.offsetWidth, y: this.offsetHeight}; + }, + + getScrollSize: function(){ + if (isBody(this)) return this.getWindow().getScrollSize(); + return {x: this.scrollWidth, y: this.scrollHeight}; + }, + + getScroll: function(){ + if (isBody(this)) return this.getWindow().getScroll(); + return {x: this.scrollLeft, y: this.scrollTop}; + }, + + getScrolls: function(){ + var element = this.parentNode, position = {x: 0, y: 0}; + while (element && !isBody(element)){ + position.x += element.scrollLeft; + position.y += element.scrollTop; + element = element.parentNode; + } + return position; + }, + + getOffsetParent: brokenOffsetParent ? function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset; + while ((element = element.parentNode)){ + if (isOffsetCheck(element)) return element; + } + return null; + } : function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + try { + return element.offsetParent; + } catch(e) {} + return null; + }, + + getOffsets: function(){ + var hasGetBoundingClientRect = this.getBoundingClientRect; + + if (hasGetBoundingClientRect){ + var bound = this.getBoundingClientRect(), + html = document.id(this.getDocument().documentElement), + htmlScroll = html.getScroll(), + elemScrolls = this.getScrolls(), + isFixed = (styleString(this, 'position') == 'fixed'); + + return { + x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, + y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop + }; + } + + var element = this, position = {x: 0, y: 0}; + if (isBody(this)) return position; + + while (element && !isBody(element)){ + position.x += element.offsetLeft; + position.y += element.offsetTop; + + element = element.offsetParent; + } + + return position; + }, + + getPosition: function(relative){ + var offset = this.getOffsets(), + scroll = this.getScrolls(); + var position = { + x: offset.x - scroll.x, + y: offset.y - scroll.y + }; + + if (relative && (relative = document.id(relative))){ + var relativePosition = relative.getPosition(); + return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; + } + return position; + }, + + getCoordinates: function(element){ + if (isBody(this)) return this.getWindow().getCoordinates(); + var position = this.getPosition(element), + size = this.getSize(); + var obj = { + left: position.x, + top: position.y, + width: size.x, + height: size.y + }; + obj.right = obj.left + obj.width; + obj.bottom = obj.top + obj.height; + return obj; + }, + + computePosition: function(obj){ + return { + left: obj.x - styleNumber(this, 'margin-left'), + top: obj.y - styleNumber(this, 'margin-top') + }; + }, + + setPosition: function(obj){ + return this.setStyles(this.computePosition(obj)); + } + +}); + + +[Document, Window].invoke('implement', { + + getSize: function(){ + var doc = getCompatElement(this); + return {x: doc.clientWidth, y: doc.clientHeight}; + }, + + getScroll: function(){ + var win = this.getWindow(), doc = getCompatElement(this); + return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; + }, + + getScrollSize: function(){ + var doc = getCompatElement(this), + min = this.getSize(), + body = this.getDocument().body; + + return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)}; + }, + + getPosition: function(){ + return {x: 0, y: 0}; + }, + + getCoordinates: function(){ + var size = this.getSize(); + return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; + } + +}); + +// private methods + +var styleString = Element.getComputedStyle; + +function styleNumber(element, style){ + return styleString(element, style).toInt() || 0; +} + +function borderBox(element){ + return styleString(element, '-moz-box-sizing') == 'border-box'; +} + +function topBorder(element){ + return styleNumber(element, 'border-top-width'); +} + +function leftBorder(element){ + return styleNumber(element, 'border-left-width'); +} + +function isBody(element){ + return (/^(?:body|html)$/i).test(element.tagName); +} + +function getCompatElement(element){ + var doc = element.getDocument(); + return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; +} + +})(); + +//aliases +Element.alias({position: 'setPosition'}); //compatability + +[Window, Document, Element].invoke('implement', { + + getHeight: function(){ + return this.getSize().y; + }, + + getWidth: function(){ + return this.getSize().x; + }, + + getScrollTop: function(){ + return this.getScroll().y; + }, + + getScrollLeft: function(){ + return this.getScroll().x; + }, + + getScrollHeight: function(){ + return this.getScrollSize().y; + }, + + getScrollWidth: function(){ + return this.getScrollSize().x; + }, + + getTop: function(){ + return this.getPosition().y; + }, + + getLeft: function(){ + return this.getPosition().x; + } + +}); + + +/* +--- + +name: Fx + +description: Contains the basic animation logic to be extended by all other Fx Classes. + +license: MIT-style license. + +requires: [Chain, Events, Options] + +provides: Fx + +... +*/ + +(function(){ + +var Fx = this.Fx = new Class({ + + Implements: [Chain, Events, Options], + + options: { + /* + onStart: nil, + onCancel: nil, + onComplete: nil, + */ + fps: 60, + unit: false, + duration: 500, + frames: null, + frameSkip: true, + link: 'ignore' + }, + + initialize: function(options){ + this.subject = this.subject || this; + this.setOptions(options); + }, + + getTransition: function(){ + return function(p){ + return -(Math.cos(Math.PI * p) - 1) / 2; + }; + }, + + step: function(now){ + if (this.options.frameSkip){ + var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval; + this.time = now; + this.frame += frames; + } else { + this.frame++; + } + + if (this.frame < this.frames){ + var delta = this.transition(this.frame / this.frames); + this.set(this.compute(this.from, this.to, delta)); + } else { + this.frame = this.frames; + this.set(this.compute(this.from, this.to, 1)); + this.stop(); + } + }, + + set: function(now){ + return now; + }, + + compute: function(from, to, delta){ + return Fx.compute(from, to, delta); + }, + + check: function(){ + if (!this.isRunning()) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + start: function(from, to){ + if (!this.check(from, to)) return this; + this.from = from; + this.to = to; + this.frame = (this.options.frameSkip) ? 0 : -1; + this.time = null; + this.transition = this.getTransition(); + var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration; + this.duration = Fx.Durations[duration] || duration.toInt(); + this.frameInterval = 1000 / fps; + this.frames = frames || Math.round(this.duration / this.frameInterval); + this.fireEvent('start', this.subject); + pushInstance.call(this, fps); + return this; + }, + + stop: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + if (this.frames == this.frame){ + this.fireEvent('complete', this.subject); + if (!this.callChain()) this.fireEvent('chainComplete', this.subject); + } else { + this.fireEvent('stop', this.subject); + } + } + return this; + }, + + cancel: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + this.frame = this.frames; + this.fireEvent('cancel', this.subject).clearChain(); + } + return this; + }, + + pause: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + } + return this; + }, + + resume: function(){ + if (this.isPaused()) pushInstance.call(this, this.options.fps); + return this; + }, + + isRunning: function(){ + var list = instances[this.options.fps]; + return list && list.contains(this); + }, + + isPaused: function(){ + return (this.frame < this.frames) && !this.isRunning(); + } + +}); + +Fx.compute = function(from, to, delta){ + return (to - from) * delta + from; +}; + +Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; + +// global timers + +var instances = {}, timers = {}; + +var loop = function(){ + var now = Date.now(); + for (var i = this.length; i--;){ + var instance = this[i]; + if (instance) instance.step(now); + } +}; + +var pushInstance = function(fps){ + var list = instances[fps] || (instances[fps] = []); + list.push(this); + if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list); +}; + +var pullInstance = function(fps){ + var list = instances[fps]; + if (list){ + list.erase(this); + if (!list.length && timers[fps]){ + delete instances[fps]; + timers[fps] = clearInterval(timers[fps]); + } + } +}; + +})(); + + +/* +--- + +name: Fx.CSS + +description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. + +license: MIT-style license. + +requires: [Fx, Element.Style] + +provides: Fx.CSS + +... +*/ + +Fx.CSS = new Class({ + + Extends: Fx, + + //prepares the base from/to object + + prepare: function(element, property, values){ + values = Array.from(values); + var from = values[0], to = values[1]; + if (to == null){ + to = from; + from = element.getStyle(property); + var unit = this.options.unit; + // adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299 + if (unit && from && typeof from == 'string' && from.slice(-unit.length) != unit && parseFloat(from) != 0){ + element.setStyle(property, to + unit); + var value = element.getComputedStyle(property); + // IE and Opera support pixelLeft or pixelWidth + if (!(/px$/.test(value))){ + value = element.style[('pixel-' + property).camelCase()]; + if (value == null){ + // adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + var left = element.style.left; + element.style.left = to + unit; + value = element.style.pixelLeft; + element.style.left = left; + } + } + from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0); + element.setStyle(property, from + unit); + } + } + return {from: this.parse(from), to: this.parse(to)}; + }, + + //parses a value into an array + + parse: function(value){ + value = Function.from(value)(); + value = (typeof value == 'string') ? value.split(' ') : Array.from(value); + return value.map(function(val){ + val = String(val); + var found = false; + Object.each(Fx.CSS.Parsers, function(parser, key){ + if (found) return; + var parsed = parser.parse(val); + if (parsed || parsed === 0) found = {value: parsed, parser: parser}; + }); + found = found || {value: val, parser: Fx.CSS.Parsers.String}; + return found; + }); + }, + + //computes by a from and to prepared objects, using their parsers. + + compute: function(from, to, delta){ + var computed = []; + (Math.min(from.length, to.length)).times(function(i){ + computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); + }); + computed.$family = Function.from('fx:css:value'); + return computed; + }, + + //serves the value as settable + + serve: function(value, unit){ + if (typeOf(value) != 'fx:css:value') value = this.parse(value); + var returned = []; + value.each(function(bit){ + returned = returned.concat(bit.parser.serve(bit.value, unit)); + }); + return returned; + }, + + //renders the change to an element + + render: function(element, property, value, unit){ + element.setStyle(property, this.serve(value, unit)); + }, + + //searches inside the page css to find the values for a selector + + search: function(selector){ + if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; + var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); + + var searchStyles = function(rules){ + Array.each(rules, function(rule, i){ + if (rule.media){ + searchStyles(rule.rules || rule.cssRules); + return; + } + if (!rule.style) return; + var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ + return m.toLowerCase(); + }) : null; + if (!selectorText || !selectorTest.test(selectorText)) return; + Object.each(Element.Styles, function(value, style){ + if (!rule.style[style] || Element.ShortStyles[style]) return; + value = String(rule.style[style]); + to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; + }); + }); + }; + + Array.each(document.styleSheets, function(sheet, j){ + var href = sheet.href; + if (href && href.indexOf('://') > -1 && href.indexOf(document.domain) == -1) return; + var rules = sheet.rules || sheet.cssRules; + searchStyles(rules); + }); + return Fx.CSS.Cache[selector] = to; + } + +}); + +Fx.CSS.Cache = {}; + +Fx.CSS.Parsers = { + + Color: { + parse: function(value){ + if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); + return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; + }, + compute: function(from, to, delta){ + return from.map(function(value, i){ + return Math.round(Fx.compute(from[i], to[i], delta)); + }); + }, + serve: function(value){ + return value.map(Number); + } + }, + + Number: { + parse: parseFloat, + compute: Fx.compute, + serve: function(value, unit){ + return (unit) ? value + unit : value; + } + }, + + String: { + parse: Function.from(false), + compute: function(zero, one){ + return one; + }, + serve: function(zero){ + return zero; + } + } + +}; + + + + +/* +--- + +name: Fx.Tween + +description: Formerly Fx.Style, effect to transition any CSS property for an element. + +license: MIT-style license. + +requires: Fx.CSS + +provides: [Fx.Tween, Element.fade, Element.highlight] + +... +*/ + +Fx.Tween = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(property, now){ + if (arguments.length == 1){ + now = property; + property = this.property || this.options.property; + } + this.render(this.element, property, now, this.options.unit); + return this; + }, + + start: function(property, from, to){ + if (!this.check(property, from, to)) return this; + var args = Array.flatten(arguments); + this.property = this.options.property || args.shift(); + var parsed = this.prepare(this.element, this.property, args); + return this.parent(parsed.from, parsed.to); + } + +}); + +Element.Properties.tween = { + + set: function(options){ + this.get('tween').cancel().setOptions(options); + return this; + }, + + get: function(){ + var tween = this.retrieve('tween'); + if (!tween){ + tween = new Fx.Tween(this, {link: 'cancel'}); + this.store('tween', tween); + } + return tween; + } + +}; + +Element.implement({ + + tween: function(property, from, to){ + this.get('tween').start(property, from, to); + return this; + }, + + fade: function(how){ + var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle; + if (args[1] == null) args[1] = 'toggle'; + switch (args[1]){ + case 'in': method = 'start'; args[1] = 1; break; + case 'out': method = 'start'; args[1] = 0; break; + case 'show': method = 'set'; args[1] = 1; break; + case 'hide': method = 'set'; args[1] = 0; break; + case 'toggle': + var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1); + method = 'start'; + args[1] = flag ? 0 : 1; + this.store('fade:flag', !flag); + toggle = true; + break; + default: method = 'start'; + } + if (!toggle) this.eliminate('fade:flag'); + fade[method].apply(fade, args); + var to = args[args.length - 1]; + if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible'); + else fade.chain(function(){ + this.element.setStyle('visibility', 'hidden'); + this.callChain(); + }); + return this; + }, + + highlight: function(start, end){ + if (!end){ + end = this.retrieve('highlight:original', this.getStyle('background-color')); + end = (end == 'transparent') ? '#fff' : end; + } + var tween = this.get('tween'); + tween.start('background-color', start || '#ffff88', end).chain(function(){ + this.setStyle('background-color', this.retrieve('highlight:original')); + tween.callChain(); + }.bind(this)); + return this; + } + +}); + + +/* +--- + +name: Fx.Morph + +description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. + +license: MIT-style license. + +requires: Fx.CSS + +provides: Fx.Morph + +... +*/ + +Fx.Morph = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(now){ + if (typeof now == 'string') now = this.search(now); + for (var p in now) this.render(this.element, p, now[p], this.options.unit); + return this; + }, + + compute: function(from, to, delta){ + var now = {}; + for (var p in from) now[p] = this.parent(from[p], to[p], delta); + return now; + }, + + start: function(properties){ + if (!this.check(properties)) return this; + if (typeof properties == 'string') properties = this.search(properties); + var from = {}, to = {}; + for (var p in properties){ + var parsed = this.prepare(this.element, p, properties[p]); + from[p] = parsed.from; + to[p] = parsed.to; + } + return this.parent(from, to); + } + +}); + +Element.Properties.morph = { + + set: function(options){ + this.get('morph').cancel().setOptions(options); + return this; + }, + + get: function(){ + var morph = this.retrieve('morph'); + if (!morph){ + morph = new Fx.Morph(this, {link: 'cancel'}); + this.store('morph', morph); + } + return morph; + } + +}; + +Element.implement({ + + morph: function(props){ + this.get('morph').start(props); + return this; + } + +}); + + +/* +--- + +name: Fx.Transitions + +description: Contains a set of advanced transitions to be used with any of the Fx Classes. + +license: MIT-style license. + +credits: + - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. + +requires: Fx + +provides: Fx.Transitions + +... +*/ + +Fx.implement({ + + getTransition: function(){ + var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; + if (typeof trans == 'string'){ + var data = trans.split(':'); + trans = Fx.Transitions; + trans = trans[data[0]] || trans[data[0].capitalize()]; + if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; + } + return trans; + } + +}); + +Fx.Transition = function(transition, params){ + params = Array.from(params); + var easeIn = function(pos){ + return transition(pos, params); + }; + return Object.append(easeIn, { + easeIn: easeIn, + easeOut: function(pos){ + return 1 - transition(1 - pos, params); + }, + easeInOut: function(pos){ + return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2; + } + }); +}; + +Fx.Transitions = { + + linear: function(zero){ + return zero; + } + +}; + + + +Fx.Transitions.extend = function(transitions){ + for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); +}; + +Fx.Transitions.extend({ + + Pow: function(p, x){ + return Math.pow(p, x && x[0] || 6); + }, + + Expo: function(p){ + return Math.pow(2, 8 * (p - 1)); + }, + + Circ: function(p){ + return 1 - Math.sin(Math.acos(p)); + }, + + Sine: function(p){ + return 1 - Math.cos(p * Math.PI / 2); + }, + + Back: function(p, x){ + x = x && x[0] || 1.618; + return Math.pow(p, 2) * ((x + 1) * p - x); + }, + + Bounce: function(p){ + var value; + for (var a = 0, b = 1; 1; a += b, b /= 2){ + if (p >= (7 - 4 * a) / 11){ + value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); + break; + } + } + return value; + }, + + Elastic: function(p, x){ + return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3); + } + +}); + +['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ + Fx.Transitions[transition] = new Fx.Transition(function(p){ + return Math.pow(p, i + 2); + }); +}); + + +/* +--- + +name: Request + +description: Powerful all purpose Request Class. Uses XMLHTTPRequest. + +license: MIT-style license. + +requires: [Object, Element, Chain, Events, Options, Browser] + +provides: Request + +... +*/ + +(function(){ + +var empty = function(){}, + progressSupport = ('onprogress' in new Browser.Request); + +var Request = this.Request = new Class({ + + Implements: [Chain, Events, Options], + + options: {/* + onRequest: function(){}, + onLoadstart: function(event, xhr){}, + onProgress: function(event, xhr){}, + onComplete: function(){}, + onCancel: function(){}, + onSuccess: function(responseText, responseXML){}, + onFailure: function(xhr){}, + onException: function(headerName, value){}, + onTimeout: function(){}, + user: '', + password: '',*/ + url: '', + data: '', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }, + async: true, + format: false, + method: 'post', + link: 'ignore', + isSuccess: null, + emulation: true, + urlEncoded: true, + encoding: 'utf-8', + evalScripts: false, + evalResponse: false, + timeout: 0, + noCache: false + }, + + initialize: function(options){ + this.xhr = new Browser.Request(); + this.setOptions(options); + this.headers = this.options.headers; + }, + + onStateChange: function(){ + var xhr = this.xhr; + if (xhr.readyState != 4 || !this.running) return; + this.running = false; + this.status = 0; + Function.attempt(function(){ + var status = xhr.status; + this.status = (status == 1223) ? 204 : status; + }.bind(this)); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + clearTimeout(this.timer); + + this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; + if (this.options.isSuccess.call(this, this.status)) + this.success(this.response.text, this.response.xml); + else + this.failure(); + }, + + isSuccess: function(){ + var status = this.status; + return (status >= 200 && status < 300); + }, + + isRunning: function(){ + return !!this.running; + }, + + processScripts: function(text){ + if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text); + return text.stripScripts(this.options.evalScripts); + }, + + success: function(text, xml){ + this.onSuccess(this.processScripts(text), xml); + }, + + onSuccess: function(){ + this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); + }, + + failure: function(){ + this.onFailure(); + }, + + onFailure: function(){ + this.fireEvent('complete').fireEvent('failure', this.xhr); + }, + + loadstart: function(event){ + this.fireEvent('loadstart', [event, this.xhr]); + }, + + progress: function(event){ + this.fireEvent('progress', [event, this.xhr]); + }, + + timeout: function(){ + this.fireEvent('timeout', this.xhr); + }, + + setHeader: function(name, value){ + this.headers[name] = value; + return this; + }, + + getHeader: function(name){ + return Function.attempt(function(){ + return this.xhr.getResponseHeader(name); + }.bind(this)); + }, + + check: function(){ + if (!this.running) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + send: function(options){ + if (!this.check(options)) return this; + + this.options.isSuccess = this.options.isSuccess || this.isSuccess; + this.running = true; + + var type = typeOf(options); + if (type == 'string' || type == 'element') options = {data: options}; + + var old = this.options; + options = Object.append({data: old.data, url: old.url, method: old.method}, options); + var data = options.data, url = String(options.url), method = options.method.toLowerCase(); + + switch (typeOf(data)){ + case 'element': data = document.id(data).toQueryString(); break; + case 'object': case 'hash': data = Object.toQueryString(data); + } + + if (this.options.format){ + var format = 'format=' + this.options.format; + data = (data) ? format + '&' + data : format; + } + + if (this.options.emulation && !['get', 'post'].contains(method)){ + var _method = '_method=' + method; + data = (data) ? _method + '&' + data : _method; + method = 'post'; + } + + if (this.options.urlEncoded && ['post', 'put'].contains(method)){ + var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; + this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; + } + + if (!url) url = document.location.pathname; + + var trimPosition = url.lastIndexOf('/'); + if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); + + if (this.options.noCache) + url += (url.indexOf('?') > -1 ? '&' : '?') + String.uniqueID(); + + if (data && (method == 'get' || method == 'delete')){ + url += (url.indexOf('?') > -1 ? '&' : '?') + data; + data = null; + } + + var xhr = this.xhr; + if (progressSupport){ + xhr.onloadstart = this.loadstart.bind(this); + xhr.onprogress = this.progress.bind(this); + } + + xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); + if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; + + xhr.onreadystatechange = this.onStateChange.bind(this); + + Object.each(this.headers, function(value, key){ + try { + xhr.setRequestHeader(key, value); + } catch (e){ + this.fireEvent('exception', [key, value]); + } + }, this); + + this.fireEvent('request'); + xhr.send(data); + if (!this.options.async) this.onStateChange(); + else if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this); + return this; + }, + + cancel: function(){ + if (!this.running) return this; + this.running = false; + var xhr = this.xhr; + xhr.abort(); + clearTimeout(this.timer); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + this.xhr = new Browser.Request(); + this.fireEvent('cancel'); + return this; + } + +}); + +var methods = {}; +['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ + methods[method] = function(data){ + var object = { + method: method + }; + if (data != null) object.data = data; + return this.send(object); + }; +}); + +Request.implement(methods); + +Element.Properties.send = { + + set: function(options){ + var send = this.get('send').cancel(); + send.setOptions(options); + return this; + }, + + get: function(){ + var send = this.retrieve('send'); + if (!send){ + send = new Request({ + data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') + }); + this.store('send', send); + } + return send; + } + +}; + +Element.implement({ + + send: function(url){ + var sender = this.get('send'); + sender.send({data: this, url: url || sender.options.url}); + return this; + } + +}); + +})(); + + +/* +--- + +name: Request.HTML + +description: Extends the basic Request Class with additional methods for interacting with HTML responses. + +license: MIT-style license. + +requires: [Element, Request] + +provides: Request.HTML + +... +*/ + +Request.HTML = new Class({ + + Extends: Request, + + options: { + update: false, + append: false, + evalScripts: true, + filter: false, + headers: { + Accept: 'text/html, application/xml, text/xml, */*' + } + }, + + success: function(text){ + var options = this.options, response = this.response; + + response.html = text.stripScripts(function(script){ + response.javascript = script; + }); + + var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); + if (match) response.html = match[1]; + var temp = new Element('div').set('html', response.html); + + response.tree = temp.childNodes; + response.elements = temp.getElements(options.filter || '*'); + + if (options.filter) response.tree = response.elements; + if (options.update){ + var update = document.id(options.update).empty(); + if (options.filter) update.adopt(response.elements); + else update.set('html', response.html); + } else if (options.append){ + var append = document.id(options.append); + if (options.filter) response.elements.reverse().inject(append); + else append.adopt(temp.getChildren()); + } + if (options.evalScripts) Browser.exec(response.javascript); + + this.onSuccess(response.tree, response.elements, response.html, response.javascript); + } + +}); + +Element.Properties.load = { + + set: function(options){ + var load = this.get('load').cancel(); + load.setOptions(options); + return this; + }, + + get: function(){ + var load = this.retrieve('load'); + if (!load){ + load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'}); + this.store('load', load); + } + return load; + } + +}; + +Element.implement({ + + load: function(){ + this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString})); + return this; + } + +}); + + +/* +--- + +name: JSON + +description: JSON encoder and decoder. + +license: MIT-style license. + +SeeAlso: <http://www.json.org/> + +requires: [Array, String, Number, Function] + +provides: JSON + +... +*/ + +if (typeof JSON == 'undefined') this.JSON = {}; + + + +(function(){ + +var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; + +var escape = function(chr){ + return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); +}; + +JSON.validate = function(string){ + string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''); + + return (/^[\],:{}\s]*$/).test(string); +}; + +JSON.encode = JSON.stringify ? function(obj){ + return JSON.stringify(obj); +} : function(obj){ + if (obj && obj.toJSON) obj = obj.toJSON(); + + switch (typeOf(obj)){ + case 'string': + return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; + case 'array': + return '[' + obj.map(JSON.encode).clean() + ']'; + case 'object': case 'hash': + var string = []; + Object.each(obj, function(value, key){ + var json = JSON.encode(value); + if (json) string.push(JSON.encode(key) + ':' + json); + }); + return '{' + string + '}'; + case 'number': case 'boolean': return '' + obj; + case 'null': return 'null'; + } + + return null; +}; + +JSON.secure = true; + + +JSON.decode = function(string, secure){ + if (!string || typeOf(string) != 'string') return null; + + if (secure == null) secure = JSON.secure; + if (secure){ + if (JSON.parse) return JSON.parse(string); + if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); + } + + return eval('(' + string + ')'); +}; + +})(); + + +/* +--- + +name: Request.JSON + +description: Extends the basic Request Class with additional methods for sending and receiving JSON data. + +license: MIT-style license. + +requires: [Request, JSON] + +provides: Request.JSON + +... +*/ + +Request.JSON = new Class({ + + Extends: Request, + + options: { + /*onError: function(text, error){},*/ + secure: true + }, + + initialize: function(options){ + this.parent(options); + Object.append(this.headers, { + 'Accept': 'application/json', + 'X-Request': 'JSON' + }); + }, + + success: function(text){ + var json; + try { + json = this.response.json = JSON.decode(text, this.options.secure); + } catch (error){ + this.fireEvent('error', [text, error]); + return; + } + if (json == null) this.onFailure(); + else this.onSuccess(json, text); + } + +}); + + +/* +--- + +name: Cookie + +description: Class for creating, reading, and deleting browser Cookies. + +license: MIT-style license. + +credits: + - Based on the functions by Peter-Paul Koch (http://quirksmode.org). + +requires: [Options, Browser] + +provides: Cookie + +... +*/ + +var Cookie = new Class({ + + Implements: Options, + + options: { + path: '/', + domain: false, + duration: false, + secure: false, + document: document, + encode: true + }, + + initialize: function(key, options){ + this.key = key; + this.setOptions(options); + }, + + write: function(value){ + if (this.options.encode) value = encodeURIComponent(value); + if (this.options.domain) value += '; domain=' + this.options.domain; + if (this.options.path) value += '; path=' + this.options.path; + if (this.options.duration){ + var date = new Date(); + date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); + value += '; expires=' + date.toGMTString(); + } + if (this.options.secure) value += '; secure'; + this.options.document.cookie = this.key + '=' + value; + return this; + }, + + read: function(){ + var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); + return (value) ? decodeURIComponent(value[1]) : null; + }, + + dispose: function(){ + new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write(''); + return this; + } + +}); + +Cookie.write = function(key, value, options){ + return new Cookie(key, options).write(value); +}; + +Cookie.read = function(key){ + return new Cookie(key).read(); +}; + +Cookie.dispose = function(key, options){ + return new Cookie(key, options).dispose(); +}; + + +/* +--- + +name: DOMReady + +description: Contains the custom event domready. + +license: MIT-style license. + +requires: [Browser, Element, Element.Event] + +provides: [DOMReady, DomReady] + +... +*/ + +(function(window, document){ + +var ready, + loaded, + checks = [], + shouldPoll, + timer, + testElement = document.createElement('div'); + +var domready = function(){ + clearTimeout(timer); + if (ready) return; + Browser.loaded = ready = true; + document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); + + document.fireEvent('domready'); + window.fireEvent('domready'); +}; + +var check = function(){ + for (var i = checks.length; i--;) if (checks[i]()){ + domready(); + return true; + } + return false; +}; + +var poll = function(){ + clearTimeout(timer); + if (!check()) timer = setTimeout(poll, 10); +}; + +document.addListener('DOMContentLoaded', domready); + +/*<ltIE8>*/ +// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/ +// testElement.doScroll() throws when the DOM is not ready, only in the top window +var doScrollWorks = function(){ + try { + testElement.doScroll(); + return true; + } catch (e){} + return false; +}; +// If doScroll works already, it can't be used to determine domready +// e.g. in an iframe +if (testElement.doScroll && !doScrollWorks()){ + checks.push(doScrollWorks); + shouldPoll = true; +} +/*</ltIE8>*/ + +if (document.readyState) checks.push(function(){ + var state = document.readyState; + return (state == 'loaded' || state == 'complete'); +}); + +if ('onreadystatechange' in document) document.addListener('readystatechange', check); +else shouldPoll = true; + +if (shouldPoll) poll(); + +Element.Events.domready = { + onAdd: function(fn){ + if (ready) fn.call(this); + } +}; + +// Make sure that domready fires before load +Element.Events.load = { + base: 'load', + onAdd: function(fn){ + if (loaded && this == window) fn.call(this); + }, + condition: function(){ + if (this == window){ + domready(); + delete Element.Events.load; + } + return true; + } +}; + +// This is based on the custom load event +window.addEvent('load', function(){ + loaded = true; +}); + +})(window, document); + diff --git a/module/webui/themes/flat/js/static/mootools-core.min.js b/module/webui/themes/flat/js/static/mootools-core.min.js new file mode 100644 index 000000000..354f94196 --- /dev/null +++ b/module/webui/themes/flat/js/static/mootools-core.min.js @@ -0,0 +1,491 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/core/8423c12ffd6a6bfcde9ea22554aec795 + +packager build: + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady + +copyrights: + - [MooTools](http://mootools.net) + +licenses: + - [MIT License](http://mootools.net/license.txt) +... +*/ + +(function(){this.MooTools={version:"1.5.0",build:"0f7b690afee9349b15909f33016a25d2e4d9f4e3"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family!=null){return i.$family(); +}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if("callee" in i){return"arguments"; +}if("item" in i){return"collection";}}}return typeof i;};var j=this.instanceOf=function(t,i){if(t==null){return false;}var s=t.$constructor||t.constructor; +while(s){if(s===i){return true;}s=s.parent;}if(!t.hasOwnProperty){return false;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null; +}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];}f.prototype.overloadSetter=function(s){var i=this; +return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]);}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]); +}}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this;return function(u){var v,t;if(typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments; +}else{if(s){v=[u];}}}if(v){t={};for(var w=0;w<v.length;w++){t[v[w]]=i.call(this,v[w]);}}else{t=i.call(this,u);}return t;};};f.prototype.extend=function(i,s){this[i]=s; +}.overloadSetter();f.prototype.implement=function(i,s){this.prototype[i]=s;}.overloadSetter();var n=Array.prototype.slice;f.from=function(i){return(o(i)=="function")?i:function(){return i; +};};Array.from=function(i){if(i==null){return[];}return(a.isEnumerable(i)&&typeof i!="string")?(o(i)=="array")?i:n.call(i):[i];};Number.from=function(s){var i=parseFloat(s); +return isFinite(i)?i:null;};String.from=function(i){return i+"";};f.implement({hide:function(){this.$hidden=true;return this;},protect:function(){this.$protected=true; +return this;}});var a=this.Type=function(u,t){if(u){var s=u.toLowerCase();var i=function(v){return(o(v)==s);};a["is"+u]=i;if(t!=null){t.prototype.$family=(function(){return s; +}).hide();}}if(t==null){return null;}t.extend(this);t.$constructor=a;t.prototype.$constructor=t;return t;};var e=Object.prototype.toString;a.isEnumerable=function(i){return(i!=null&&typeof i.length=="number"&&e.call(i)!="[object Function]"); +};var q={};var r=function(i){var s=o(i.prototype);return q[s]||(q[s]=[]);};var b=function(t,x){if(x&&x.$hidden){return;}var s=r(this);for(var u=0;u<s.length; +u++){var w=s[u];if(o(w)=="type"){b.call(w,t,x);}else{w.call(this,t,x);}}var v=this.prototype[t];if(v==null||!v.$protected){this.prototype[t]=x;}if(this[t]==null&&o(x)=="function"){m.call(this,t,function(i){return x.apply(i,n.call(arguments,1)); +});}};var m=function(i,t){if(t&&t.$hidden){return;}var s=this[i];if(s==null||!s.$protected){this[i]=t;}};a.implement({implement:b.overloadSetter(),extend:m.overloadSetter(),alias:function(i,s){b.call(this,i,this.prototype[s]); +}.overloadSetter(),mirror:function(i){r(this).push(i);return this;}});new a("Type",a);var d=function(s,x,v){var u=(x!=Object),B=x.prototype;if(u){x=new a(s,x); +}for(var y=0,w=v.length;y<w;y++){var C=v[y],A=x[C],z=B[C];if(A){A.protect();}if(u&&z){x.implement(C,z.protect());}}if(u){var t=B.propertyIsEnumerable(v[0]); +x.forEachMethod=function(G){if(!t){for(var F=0,D=v.length;F<D;F++){G.call(B,B[v[F]],v[F]);}}for(var E in B){G.call(B,B[E],E);}};}return d;};d("String",String,["charAt","charCodeAt","concat","contains","indexOf","lastIndexOf","match","quote","replace","search","slice","split","substr","substring","trim","toLowerCase","toUpperCase"])("Array",Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"])("Number",Number,["toExponential","toFixed","toLocaleString","toPrecision"])("Function",f,["apply","call","bind"])("RegExp",RegExp,["exec","test"])("Object",Object,["create","defineProperty","defineProperties","keys","getPrototypeOf","getOwnPropertyDescriptor","getOwnPropertyNames","preventExtensions","isExtensible","seal","isSealed","freeze","isFrozen"])("Date",Date,["now"]); +Object.extend=m.overloadSetter();Date.extend("now",function(){return +(new Date);});new a("Boolean",Boolean);Number.prototype.$family=function(){return isFinite(this)?"number":"null"; +}.hide();Number.extend("random",function(s,i){return Math.floor(Math.random()*(i-s+1)+s);});var g=Object.prototype.hasOwnProperty;Object.extend("forEach",function(i,t,u){for(var s in i){if(g.call(i,s)){t.call(u,i[s],s,i); +}}});Object.each=Object.forEach;Array.implement({forEach:function(u,v){for(var t=0,s=this.length;t<s;t++){if(t in this){u.call(v,this[t],t,this);}}},each:function(i,s){Array.forEach(this,i,s); +return this;}});var l=function(i){switch(o(i)){case"array":return i.clone();case"object":return Object.clone(i);default:return i;}};Array.implement("clone",function(){var s=this.length,t=new Array(s); +while(s--){t[s]=l(this[s]);}return t;});var h=function(s,i,t){switch(o(t)){case"object":if(o(s[i])=="object"){Object.merge(s[i],t);}else{s[i]=Object.clone(t); +}break;case"array":s[i]=t.clone();break;default:s[i]=t;}return s;};Object.extend({merge:function(z,u,t){if(o(u)=="string"){return h(z,u,t);}for(var y=1,s=arguments.length; +y<s;y++){var w=arguments[y];for(var x in w){h(z,x,w[x]);}}return z;},clone:function(i){var t={};for(var s in i){t[s]=l(i[s]);}return t;},append:function(w){for(var v=1,t=arguments.length; +v<t;v++){var s=arguments[v]||{};for(var u in s){w[u]=s[u];}}return w;}});["Object","WhiteSpace","TextNode","Collection","Arguments"].each(function(i){new a(i); +});var c=Date.now();String.extend("uniqueID",function(){return(c++).toString(36);});})();Array.implement({every:function(c,d){for(var b=0,a=this.length>>>0; +b<a;b++){if((b in this)&&!c.call(d,this[b],b,this)){return false;}}return true;},filter:function(d,f){var c=[];for(var e,b=0,a=this.length>>>0;b<a;b++){if(b in this){e=this[b]; +if(d.call(f,e,b,this)){c.push(e);}}}return c;},indexOf:function(c,d){var b=this.length>>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a<b;a++){if(this[a]===c){return a; +}}return -1;},map:function(c,e){var d=this.length>>>0,b=Array(d);for(var a=0;a<d;a++){if(a in this){b[a]=c.call(e,this[a],a,this);}}return b;},some:function(c,d){for(var b=0,a=this.length>>>0; +b<a;b++){if((b in this)&&c.call(d,this[b],b,this)){return true;}}return false;},clean:function(){return this.filter(function(a){return a!=null;});},invoke:function(a){var b=Array.slice(arguments,1); +return this.map(function(c){return c[a].apply(c,b);});},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a]; +}return d;},link:function(c){var a={};for(var e=0,b=this.length;e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1; +},append:function(a){this.push.apply(this,a);return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[Number.random(0,this.length-1)]:null; +},include:function(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this; +},erase:function(b){for(var a=this.length;a--;){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[]; +for(var b=0,a=this.length;b<a;b++){var c=typeOf(this[b]);if(c=="null"){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments"||instanceOf(this[b],Array))?Array.flatten(this[b]):this[b]); +}return d;},pick:function(){for(var b=0,a=this.length;b<a;b++){if(this[b]!=null){return this[b];}}return null;},hexToRgb:function(b){if(this.length!=3){return null; +}var a=this.map(function(c){if(c.length==1){c+=c;}return parseInt(c,16);});return(b)?a:"rgb("+a+")";},rgbToHex:function(d){if(this.length<3){return null; +}if(this.length==4&&this[3]==0&&!d){return"transparent";}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join(""); +}});String.implement({contains:function(b,a){return(a?String(this).slice(a):String(this)).indexOf(b)>-1;},test:function(a,b){return((typeOf(a)=="regexp")?a:new RegExp(""+a,b)).test(this); +},trim:function(){return String(this).replace(/^\s+|\s+$/g,"");},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase(); +});},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase(); +});},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this); +},hexToRgb:function(b){var a=String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g); +return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return String(this).replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1); +}return(a[c]!=null)?a[c]:"";});}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0).toFixed(a<0?-a:0); +return Math.round(this*a)/a;},times:function(b,c){for(var a=0;a<this;a++){b.call(c,a,this);}},toFloat:function(){return parseFloat(this);},toInt:function(a){return parseInt(this,a||10); +}});Number.alias("each","times");(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat(Array.from(arguments))); +};}});Number.implement(a);})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);Function.extend({attempt:function(){for(var b=0,a=arguments.length; +b<a;b++){try{return arguments[b]();}catch(c){}}return null;}});Function.implement({attempt:function(a,c){try{return this.apply(c,Array.from(a));}catch(b){}return null; +},bind:function(e){var a=this,b=arguments.length>1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype; +g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;},pass:function(b,c){var a=this; +if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b); +},periodical:function(c,b,a){return setInterval(this.pass((a==null?[]:a),b),c);}});(function(){var a=Object.prototype.hasOwnProperty;Object.extend({subset:function(d,g){var f={}; +for(var e=0,b=g.length;e<b;e++){var c=g[e];if(c in d){f[c]=d[c];}}return f;},map:function(b,e,f){var d={};for(var c in b){if(a.call(b,c)){d[c]=e.call(f,b[c],c,b); +}}return d;},filter:function(b,e,g){var d={};for(var c in b){var f=b[c];if(a.call(b,c)&&e.call(g,f,c,b)){d[c]=f;}}return d;},every:function(b,d,e){for(var c in b){if(a.call(b,c)&&!d.call(e,b[c],c)){return false; +}}return true;},some:function(b,d,e){for(var c in b){if(a.call(b,c)&&d.call(e,b[c],c)){return true;}}return false;},keys:function(b){var d=[];for(var c in b){if(a.call(b,c)){d.push(c); +}}return d;},values:function(c){var b=[];for(var d in c){if(a.call(c,d)){b.push(c[d]);}}return b;},getLength:function(b){return Object.keys(b).length;},keyOf:function(b,d){for(var c in b){if(a.call(b,c)&&b[c]===d){return c; +}}return null;},contains:function(b,c){return Object.keyOf(b,c)!=null;},toQueryString:function(b,c){var d=[];Object.each(b,function(h,g){if(c){g=c+"["+g+"]"; +}var f;switch(typeOf(h)){case"object":f=Object.toQueryString(h,g);break;case"array":var e={};h.each(function(k,j){e[j]=k;});f=Object.toQueryString(e,g); +break;default:f=g+"="+encodeURIComponent(h);}if(h!=null){d.push(f);}});return d.join("&");}});})();(function(){var f=this.document;var d=f.window=this; +var a=function(k,e){k=k.toLowerCase();e=(e?e.toLowerCase():"");var l=k.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/)||[null,"unknown",0]; +if(l[1]=="trident"){l[1]="ie";if(l[4]){l[2]=l[4];}}else{if(l[1]=="crios"){l[1]="chrome";}}var e=k.match(/ip(?:ad|od|hone)/)?"ios":(k.match(/(?:webos|android)/)||e.match(/mac|win|linux/)||["other"])[0]; +if(e=="win"){e="windows";}return{extend:Function.prototype.extend,name:(l[1]=="version")?l[3]:l[1],version:parseFloat((l[1]=="opera"&&l[4])?l[4]:l[2]),platform:e}; +};var j=this.Browser=a(navigator.userAgent,navigator.platform);if(j.ie){j.version=f.documentMode;}j.extend({Features:{xpath:!!(f.evaluate),air:!!(d.runtime),query:!!(f.querySelector),json:!!(d.JSON)},parseUA:a}); +j.Request=(function(){var l=function(){return new XMLHttpRequest();};var k=function(){return new ActiveXObject("MSXML2.XMLHTTP");};var e=function(){return new ActiveXObject("Microsoft.XMLHTTP"); +};return Function.attempt(function(){l();return l;},function(){k();return k;},function(){e();return e;});})();j.Features.xhr=!!(j.Request);j.exec=function(k){if(!k){return k; +}if(d.execScript){d.execScript(k);}else{var e=f.createElement("script");e.setAttribute("type","text/javascript");e.text=k;f.head.appendChild(e);f.head.removeChild(e); +}return k;};String.implement("stripScripts",function(k){var e="";var l=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(m,n){e+=n+"\n";return""; +});if(k===true){j.exec(e);}else{if(typeOf(k)=="function"){k(e,l);}}return l;});j.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event}); +this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,k){d[e]=k;});this.Document=f.$constructor=new Type("Document",function(){}); +f.$family=Function.from("document").hide();Document.mirror(function(e,k){f[e]=k;});f.html=f.documentElement;if(!f.head){f.head=f.getElementsByTagName("head")[0]; +}if(f.execCommand){try{f.execCommand("BackgroundImageCache",false,true);}catch(c){}}if(this.attachEvent&&!this.addEventListener){var b=function(){this.detachEvent("onunload",b); +f.head=f.html=f.window=null;};this.attachEvent("onunload",b);}var g=Array.from;try{g(f.html.childNodes);}catch(c){Array.from=function(k){if(typeof k!="string"&&Type.isEnumerable(k)&&typeOf(k)!="array"){var e=k.length,l=new Array(e); +while(e--){l[e]=k[e];}return l;}return g(k);};var h=Array.prototype,i=h.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var k=h[e]; +Array[e]=function(l){return k.apply(Array.from(l),i.call(arguments,1));};});}})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window; +}c=c||g.event;if(c.$extended){return c;}this.event=c;this.$extended=true;this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey; +var i=this.type=c.type;var h=c.target||c.srcElement;while(h&&h.nodeType==3){h=h.parentNode;}this.target=document.id(h);if(i.indexOf("key")==0){var d=this.code=(c.which||c.keyCode); +this.key=b[d];if(i=="keydown"||i=="keyup"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase(); +}}else{if(i=="click"||i=="dblclick"||i=="contextmenu"||i=="DOMMouseScroll"||i.indexOf("mouse")==0){var j=g.document;j=(!j.compatMode||j.compatMode=="CSS1Compat")?j.html:j.body; +this.page={x:(c.pageX!=null)?c.pageX:c.clientX+j.scrollLeft,y:(c.pageY!=null)?c.pageY:c.clientY+j.scrollTop};this.client={x:(c.pageX!=null)?c.pageX-g.pageXOffset:c.clientX,y:(c.pageY!=null)?c.pageY-g.pageYOffset:c.clientY}; +if(i=="DOMMouseScroll"||i=="mousewheel"){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3;}this.rightClick=(c.which==3||c.button==2);if(i=="mouseover"||i=="mouseout"){var k=c.relatedTarget||c[(i=="mouseover"?"from":"to")+"Element"]; +while(k&&k.nodeType==3){k=k.parentNode;}this.relatedTarget=document.id(k);}}else{if(i.indexOf("touch")==0||i.indexOf("gesture")==0){this.rotation=c.rotation; +this.scale=c.scale;this.targetTouches=c.targetTouches;this.changedTouches=c.changedTouches;var f=this.touches=c.touches;if(f&&f[0]){var e=f[0];this.page={x:e.pageX,y:e.pageY}; +this.client={x:e.clientX,y:e.clientY};}}}}if(!this.client){this.client={};}if(!this.page){this.page={};}});a.implement({stop:function(){return this.preventDefault().stopPropagation(); +},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault(); +}else{this.event.returnValue=false;}return this;}});a.defineKey=function(d,c){b[d]=c;return this;};a.defineKeys=a.defineKey.overloadSetter(true);a.defineKeys({"38":"up","40":"down","37":"left","39":"right","27":"esc","32":"space","8":"backspace","9":"tab","46":"delete","13":"enter"}); +})();(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h};}var g=function(){e(this);if(g.$prototyping){return this; +}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null;return i;}.extend(this).implement(h); +g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.'); +}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments); +};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone(); +break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.'); +}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h}); +return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this; +}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping; +return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j; +for(var i in h){f.call(this,i,h[i],true);}},this);}};})();(function(){this.Chain=new Class({$chain:[],chain:function(){this.$chain.append(Array.flatten(arguments)); +return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){this.$chain.empty(); +return this;}});var a=function(b){return b.replace(/^on([A-Z])/,function(c,d){return d.toLowerCase();});};this.Events=new Class({$events:{},addEvent:function(d,c,b){d=a(d); +this.$events[d]=(this.$events[d]||[]).include(c);if(b){c.internal=true;}return this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this; +},fireEvent:function(e,c,b){e=a(e);var d=this.$events[e];if(!d){return this;}c=Array.from(c);d.each(function(f){if(b){f.delay(b,this,c);}else{f.apply(this,c); +}},this);return this;},removeEvent:function(e,d){e=a(e);var c=this.$events[e];if(c&&!d.internal){var b=c.indexOf(d);if(b!=-1){delete c[b];}}return this; +},removeEvents:function(d){var e;if(typeOf(d)=="object"){for(e in d){this.removeEvent(e,d[e]);}return this;}if(d){d=a(d);}for(e in this.$events){if(d&&d!=e){continue; +}var c=this.$events[e];for(var b=c.length;b--;){if(b in c){this.removeEvent(e,c[b]);}}}return this;}});this.Options=new Class({setOptions:function(){var b=this.options=Object.merge.apply(null,[{},this.options].append(arguments)); +if(this.addEvent){for(var c in b){if(typeOf(b[c])!="function"||!(/^on[A-Z]/).test(c)){continue;}this.addEvent(c,b[c]);delete b[c];}}return this;}});})(); +(function(){var k,n,l,g,a={},c={},m=/\\/g;var e=function(q,p){if(q==null){return null;}if(q.Slick===true){return q;}q=(""+q).replace(/^\s+|\s+$/g,"");g=!!p; +var o=(g)?c:a;if(o[q]){return o[q];}k={Slick:true,expressions:[],raw:q,reverse:function(){return e(this.raw,true);}};n=-1;while(q!=(q=q.replace(j,b))){}k.length=k.expressions.length; +return o[k.raw]=(g)?h(k):k;};var i=function(o){if(o==="!"){return" ";}else{if(o===" "){return"!";}else{if((/^!/).test(o)){return o.replace(/^!/,"");}else{return"!"+o; +}}}};var h=function(u){var r=u.expressions;for(var p=0;p<r.length;p++){var t=r[p];var q={parts:[],tag:"*",combinator:i(t[0].combinator)};for(var o=0;o<t.length; +o++){var s=t[o];if(!s.reverseCombinator){s.reverseCombinator=" ";}s.combinator=s.reverseCombinator;delete s.reverseCombinator;}t.reverse().push(q);}return u; +};var f=function(o){return o.replace(/[-[\]{}()*+?.\\^$|,#\s]/g,function(p){return"\\"+p;});};var j=new RegExp("^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(/<combinator>/,"["+f(">+~`!@$%^&={}\\;</")+"]").replace(/<unicode>/g,"(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])").replace(/<unicode1>/g,"(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])")); +function b(x,s,D,z,r,C,q,B,A,y,u,F,G,v,p,w){if(s||n===-1){k.expressions[++n]=[];l=-1;if(s){return"";}}if(D||z||l===-1){D=D||" ";var t=k.expressions[n]; +if(g&&t[l]){t[l].reverseCombinator=i(D);}t[++l]={combinator:D,tag:"*"};}var o=k.expressions[n][l];if(r){o.tag=r.replace(m,"");}else{if(C){o.id=C.replace(m,""); +}else{if(q){q=q.replace(m,"");if(!o.classList){o.classList=[];}if(!o.classes){o.classes=[];}o.classList.push(q);o.classes.push({value:q,regexp:new RegExp("(^|\\s)"+f(q)+"(\\s|$)")}); +}else{if(G){w=w||p;w=w?w.replace(m,""):null;if(!o.pseudos){o.pseudos=[];}o.pseudos.push({key:G.replace(m,""),value:w,type:F.length==1?"class":"element"}); +}else{if(B){B=B.replace(m,"");u=(u||"").replace(m,"");var E,H;switch(A){case"^=":H=new RegExp("^"+f(u));break;case"$=":H=new RegExp(f(u)+"$");break;case"~=":H=new RegExp("(^|\\s)"+f(u)+"(\\s|$)"); +break;case"|=":H=new RegExp("^"+f(u)+"(-|$)");break;case"=":E=function(I){return u==I;};break;case"*=":E=function(I){return I&&I.indexOf(u)>-1;};break; +case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}if(u==""&&(/^[*$^]=$/).test(A)){E=function(){return false;};}if(!E){E=function(I){return I&&H.test(I); +};}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o); +};d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var k={},m={},d=Object.prototype.toString; +k.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};k.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(d.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML"); +};k.setDocument=function(w){var p=w.nodeType;if(p==9){}else{if(p){w=w.ownerDocument;}else{if(w.navigator){w=w.document;}else{return;}}}if(this.document===w){return; +}this.document=w;var A=w.documentElement,o=this.getUIDXML(A),s=m[o],r;if(s){for(r in s){this[r]=s[r];}return;}s=m[o]={};s.root=A;s.isXMLDocument=this.isXML(w); +s.brokenStarGEBTN=s.starSelectsClosedQSA=s.idGetsName=s.brokenMixedCaseQSA=s.brokenGEBCN=s.brokenCheckedQSA=s.brokenEmptyAttributeQSA=s.isHTMLDocument=s.nativeMatchesSelector=false; +var q,u,y,z,t;var x,v="slick_uniqueid";var c=w.createElement("div");var n=w.body||w.getElementsByTagName("body")[0]||A;n.appendChild(c);try{c.innerHTML='<a id="'+v+'"></a>'; +s.isHTMLDocument=!!w.getElementById(v);}catch(C){}if(s.isHTMLDocument){c.style.display="none";c.appendChild(w.createComment(""));u=(c.getElementsByTagName("*").length>1); +try{c.innerHTML="foo</foo>";x=c.getElementsByTagName("*");q=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");}catch(C){}s.brokenStarGEBTN=u||q;try{c.innerHTML='<a name="'+v+'"></a><b id="'+v+'"></b>'; +s.idGetsName=w.getElementById(v)===c.firstChild;}catch(C){}if(c.getElementsByClassName){try{c.innerHTML='<a class="f"></a><a class="b"></a>';c.getElementsByClassName("b").length; +c.firstChild.className="b";z=(c.getElementsByClassName("b").length!=2);}catch(C){}try{c.innerHTML='<a class="a"></a><a class="f b a"></a>';y=(c.getElementsByClassName("a").length!=2); +}catch(C){}s.brokenGEBCN=z||y;}if(c.querySelectorAll){try{c.innerHTML="foo</foo>";x=c.querySelectorAll("*");s.starSelectsClosedQSA=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/"); +}catch(C){}try{c.innerHTML='<a class="MiX"></a>';s.brokenMixedCaseQSA=!c.querySelectorAll(".MiX").length;}catch(C){}try{c.innerHTML='<select><option selected="selected">a</option></select>'; +s.brokenCheckedQSA=(c.querySelectorAll(":checked").length==0);}catch(C){}try{c.innerHTML='<a class=""></a>';s.brokenEmptyAttributeQSA=(c.querySelectorAll('[class*=""]').length!=0); +}catch(C){}}try{c.innerHTML='<form action="s"><input id="action"/></form>';t=(c.firstChild.getAttribute("action")!="s");}catch(C){}s.nativeMatchesSelector=A.matches||A.mozMatchesSelector||A.webkitMatchesSelector; +if(s.nativeMatchesSelector){try{s.nativeMatchesSelector.call(A,":slick");s.nativeMatchesSelector=null;}catch(C){}}}try{A.slick_expando=1;delete A.slick_expando; +s.getUID=this.getUIDHTML;}catch(C){s.getUID=this.getUIDXML;}n.removeChild(c);c=x=n=null;s.getAttribute=(s.isHTMLDocument&&t)?function(G,E){var H=this.attributeGetters[E]; +if(H){return H.call(G);}var F=G.getAttributeNode(E);return(F)?F.nodeValue:null;}:function(F,E){var G=this.attributeGetters[E];return(G)?G.call(F):F.getAttribute(E); +};s.hasAttribute=(A&&this.isNativeCode(A.hasAttribute))?function(F,E){return F.hasAttribute(E);}:function(F,E){F=F.getAttributeNode(E);return !!(F&&(F.specified||F.nodeValue)); +};var D=A&&this.isNativeCode(A.contains),B=w&&this.isNativeCode(w.contains);s.contains=(D&&B)?function(E,F){return E.contains(F);}:(D&&!B)?function(E,F){return E===F||((E===w)?w.documentElement:E).contains(F); +}:(A&&A.compareDocumentPosition)?function(E,F){return E===F||!!(E.compareDocumentPosition(F)&16);}:function(E,F){if(F){do{if(F===E){return true;}}while((F=F.parentNode)); +}return false;};s.documentSorter=(A.compareDocumentPosition)?function(F,E){if(!F.compareDocumentPosition||!E.compareDocumentPosition){return 0;}return F.compareDocumentPosition(E)&4?-1:F===E?0:1; +}:("sourceIndex" in A)?function(F,E){if(!F.sourceIndex||!E.sourceIndex){return 0;}return F.sourceIndex-E.sourceIndex;}:(w.createRange)?function(H,F){if(!H.ownerDocument||!F.ownerDocument){return 0; +}var G=H.ownerDocument.createRange(),E=F.ownerDocument.createRange();G.setStart(H,0);G.setEnd(H,0);E.setStart(F,0);E.setEnd(F,0);return G.compareBoundaryPoints(Range.START_TO_END,E); +}:null;A=null;for(r in s){this[r]=s[r];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={};k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]); +if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9);if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U); +}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f);simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors; +}E=U.getElementsByTagName(v);if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors; +}A=U.getElementById(v);if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A); +}}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v); +if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+e.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*"); +for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p); +}return(s)?null:p;}querySelector:if(U.querySelectorAll){if(!this.isHTMLDocument||g[z]||this.brokenMixedCaseQSA||(this.brokenCheckedQSA&&z.indexOf(":checked")>-1)||(this.brokenEmptyAttributeQSA&&h.test(z))||(!y&&z.indexOf(",")>-1)||e.disableQSA){break querySelector; +}var S=z,x=U;if(!y){var C=x.getAttribute("id"),t="slickid__";x.setAttribute("id",t);S="#"+t+" "+S;U=x.parentNode;}try{if(s){return U.querySelector(S)||null; +}else{E=U.querySelectorAll(S);}}catch(Q){g[z]=1;break querySelector;}finally{if(!y){if(C){x.setAttribute("id",C);}else{x.removeAttribute("id");}U=x;}}if(this.starSelectsClosedQSA){for(O=0; +A=E[O++];){if(A.nodeName>"@"&&!(I&&V[this.getUID(A)])){p.push(A);}}}else{for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}if(I){this.sort(p); +}return p;}F=this.Slick.parse(z);if(!F.length){return p;}}else{if(z==null){return p;}else{if(z.Slick){F=z;}else{if(this.contains(U.documentElement||U,z)){(p)?p.push(z):p=z; +return p;}else{return p;}}}}this.posNTH={};this.posNTHLast={};this.posNTHType={};this.posNTHTypeLast={};this.push=(!I&&(s||(F.length==1&&F.expressions[0].length==1)))?this.pushArray:this.pushUID; +if(p==null){p=[];}var M,L,K;var B,J,D,c,q,G,W;var N,P,o,w,R=F.expressions;search:for(O=0;(P=R[O]);O++){for(M=0;(o=P[M]);M++){B="combinator:"+o.combinator; +if(!this[B]){continue search;}J=(this.isXMLDocument)?o.tag:o.tag.toUpperCase();D=o.id;c=o.classList;q=o.classes;G=o.attributes;W=o.pseudos;w=(M===(P.length-1)); +this.bitUniques={};if(w){this.uniques=V;this.found=p;}else{this.uniques={};this.found=[];}if(M===0){this[B](U,J,D,q,G,W,c);if(s&&w&&p.length){break search; +}}else{if(s&&w){for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);if(p.length){break search;}}}else{for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c); +}}}N=this.found;}}if(I||(F.expressions.length>1)){this.sort(p);}return(s)?(p[0]||null):p;};k.uidx=1;k.uidk="slick-uniqueid";k.getUIDXML=function(n){var c=n.getAttribute(this.uidk); +if(!c){c=this.uidx++;n.setAttribute(this.uidk,c);}return c;};k.getUIDHTML=function(c){return c.uniqueNumber||(c.uniqueNumber=this.uidx++);};k.sort=function(c){if(!this.documentSorter){return c; +}c.sort(this.documentSorter);return c;};k.cacheNTH={};k.matchNTH=/^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;k.parseNTHArgument=function(q){var o=q.match(this.matchNTH); +if(!o){return false;}var p=o[2]||false;var n=o[1]||1;if(n=="-"){n=-1;}var c=+o[3]||0;o=(p=="n")?{a:n,b:c}:(p=="odd")?{a:2,b:1}:(p=="even")?{a:2,b:0}:{a:0,b:n}; +return(this.cacheNTH[q]=o);};k.createNTHPseudo=function(p,n,c,o){return function(s,q){var u=this.getUID(s);if(!this[c][u]){var A=s.parentNode;if(!A){return false; +}var r=A[p],t=1;if(o){var z=s.nodeName;do{if(r.nodeName!=z){continue;}this[c][this.getUID(r)]=t++;}while((r=r[n]));}else{do{if(r.nodeType!=1){continue; +}this[c][this.getUID(r)]=t++;}while((r=r[n]));}}q=q||"n";var v=this.cacheNTH[q]||this.parseNTHArgument(q);if(!v){return false;}var y=v.a,x=v.b,w=this[c][u]; +if(y==0){return x==w;}if(y>0){if(w<x){return false;}}else{if(x<w){return false;}}return((w-x)%y)==0;};};k.pushArray=function(p,c,r,o,n,q){if(this.matchSelector(p,c,r,o,n,q)){this.found.push(p); +}};k.pushUID=function(q,c,s,p,n,r){var o=this.getUID(q);if(!this.uniques[o]&&this.matchSelector(q,c,s,p,n,r)){this.uniques[o]=true;this.found.push(q);}}; +k.matchNode=function(n,o){if(this.isHTMLDocument&&this.nativeMatchesSelector){try{return this.nativeMatchesSelector.call(n,o.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g,'[$1="$2"]')); +}catch(u){}}var t=this.Slick.parse(o);if(!t){return true;}var r=t.expressions,s=0,q;for(q=0;(currentExpression=r[q]);q++){if(currentExpression.length==1){var p=currentExpression[0]; +if(this.matchSelector(n,(this.isXMLDocument)?p.tag:p.tag.toUpperCase(),p.id,p.classes,p.attributes,p.pseudos)){return true;}s++;}}if(s==t.length){return false; +}var c=this.search(this.document,t),v;for(q=0;v=c[q++];){if(v===n){return true;}}return false;};k.matchPseudo=function(q,c,p){var n="pseudo:"+c;if(this[n]){return this[n](q,p); +}var o=this.getAttribute(q,c);return(p)?p==o:!!o;};k.matchSelector=function(o,v,c,p,q,s){if(v){var t=(this.isXMLDocument)?o.nodeName:o.nodeName.toUpperCase(); +if(v=="*"){if(t<"@"){return false;}}else{if(t!=v){return false;}}}if(c&&o.getAttribute("id")!=c){return false;}var r,n,u;if(p){for(r=p.length;r--;){u=this.getAttribute(o,"class"); +if(!(u&&p[r].regexp.test(u))){return false;}}}if(q){for(r=q.length;r--;){n=q[r];if(n.operator?!n.test(this.getAttribute(o,n.key)):!this.hasAttribute(o,n.key)){return false; +}}}if(s){for(r=s.length;r--;){n=s[r];if(!this.matchPseudo(o,n.key,n.value)){return false;}}}return true;};var j={" ":function(q,w,n,r,s,u,p){var t,v,o; +if(this.isHTMLDocument){getById:if(n){v=this.document.getElementById(n);if((!v&&q.all)||(this.idGetsName&&v&&v.getAttributeNode("id").nodeValue!=n)){o=q.all[n]; +if(!o){return;}if(!o[0]){o=[o];}for(t=0;v=o[t++];){var c=v.getAttributeNode("id");if(c&&c.nodeValue==n){this.push(v,w,null,r,s,u);break;}}return;}if(!v){if(this.contains(this.root,q)){return; +}else{break getById;}}else{if(this.document!==q&&!this.contains(q,v)){return;}}this.push(v,w,null,r,s,u);return;}getByClass:if(r&&q.getElementsByClassName&&!this.brokenGEBCN){o=q.getElementsByClassName(p.join(" ")); +if(!(o&&o.length)){break getByClass;}for(t=0;v=o[t++];){this.push(v,w,n,null,s,u);}return;}}getByTag:{o=q.getElementsByTagName(w);if(!(o&&o.length)){break getByTag; +}if(!this.brokenStarGEBTN){w=null;}for(t=0;v=o[t++];){this.push(v,w,n,r,s,u);}}},">":function(p,c,r,o,n,q){if((p=p.firstChild)){do{if(p.nodeType==1){this.push(p,c,r,o,n,q); +}}while((p=p.nextSibling));}},"+":function(p,c,r,o,n,q){while((p=p.nextSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);break;}}},"^":function(p,c,r,o,n,q){p=p.firstChild; +if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:+"](p,c,r,o,n,q);}}},"~":function(q,c,s,p,n,r){while((q=q.nextSibling)){if(q.nodeType!=1){continue; +}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}},"++":function(p,c,r,o,n,q){this["combinator:+"](p,c,r,o,n,q); +this["combinator:!+"](p,c,r,o,n,q);},"~~":function(p,c,r,o,n,q){this["combinator:~"](p,c,r,o,n,q);this["combinator:!~"](p,c,r,o,n,q);},"!":function(p,c,r,o,n,q){while((p=p.parentNode)){if(p!==this.document){this.push(p,c,r,o,n,q); +}}},"!>":function(p,c,r,o,n,q){p=p.parentNode;if(p!==this.document){this.push(p,c,r,o,n,q);}},"!+":function(p,c,r,o,n,q){while((p=p.previousSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q); +break;}}},"!^":function(p,c,r,o,n,q){p=p.lastChild;if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:!+"](p,c,r,o,n,q);}}},"!~":function(q,c,s,p,n,r){while((q=q.previousSibling)){if(q.nodeType!=1){continue; +}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}}};for(var i in j){k["combinator:"+i]=j[i];}var l={empty:function(c){var n=c.firstChild; +return !(n&&n.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,n){return !this.matchNode(c,n);},contains:function(c,n){return(c.innerText||c.textContent||"").indexOf(n)>-1; +},"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false; +}}return true;},"only-child":function(o){var n=o;while((n=n.previousSibling)){if(n.nodeType==1){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeType==1){return false; +}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+(c+1)); +},even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var n=c.nodeName; +while((c=c.previousSibling)){if(c.nodeName==n){return false;}}return true;},"last-of-type":function(c){var n=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==n){return false; +}}return true;},"only-of-type":function(o){var n=o,p=o.nodeName;while((n=n.previousSibling)){if(n.nodeName==p){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeName==p){return false; +}}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex")); +},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for"); +},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href");},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style"); +},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null;},type:function(){return this.getAttribute("type"); +},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null;}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{}); +e.version="1.1.7";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true);};e.contains=function(c,n){k.setDocument(c); +return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n);return k.hasAttribute(n,c); +};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n; +return this;};e.lookupAttributeGetter=function(c){return k.attributeGetters[c];};e.definePseudo=function(c,n){k["pseudo:"+c]=function(p,o){return n.call(p,o); +};return this;};e.lookupPseudo=function(c){var n=k["pseudo:"+c];if(n){return function(o){return n.call(this,o);};}return null;};e.override=function(n,c){k.override(n,c); +return this;};e.isXML=k.isXML;e.uidOf=function(c){return k.getUIDHTML(c);};if(!this.Slick){this.Slick=e;}}).apply((typeof exports!="undefined")?exports:this); +var Element=this.Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={}; +}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0];b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length; +f<c;f++){a=d[f];if(g[a.key]!=null){continue;}if(a.value!=null&&a.operator=="="){g[a.key]=a.value;}else{if(!a.value&&!a.operator){g[a.key]=true;}}}}if(e.classList&&g["class"]==null){g["class"]=e.classList.join(" "); +}}return document.newElement(b,g);};if(Browser.Element){Element.prototype=Browser.Element.prototype;Element.prototype._fireEvent=(function(a){return function(b,c){return a.call(this,b,c); +};})(Element.prototype.fireEvent);}new Type("Element",Element).mirror(function(a){if(Array.prototype[a]){return;}var b={};b[a]=function(){var h=[],e=arguments,j=true; +for(var g=0,d=this.length;g<d;g++){var f=this[g],c=h[g]=f[a].apply(f,e);j=(j&&typeOf(c)=="element");}return(j)?new Elements(h):h;};Elements.implement(b); +});if(!Browser.Element){Element.parent=Object;Element.Prototype={"$constructor":Element,"$family":Function.from("element").hide()};Element.mirror(function(a,b){Element.Prototype[a]=b; +});}Element.Constructors={};var IFrame=new Type("IFrame",function(){var e=Array.link(arguments,{properties:Type.isObject,iframe:function(f){return(f!=null); +}});var c=e.properties||{},b;if(e.iframe){b=document.id(e.iframe);}var d=c.onload||function(){};delete c.onload;c.id=c.name=[c.id,c.name,b?(b.id||b.name):"IFrame_"+String.uniqueID()].pick(); +b=new Element(b||"iframe",c);var a=function(){d.call(b.contentWindow);};if(window.frames[c.id]){a();}else{b.addListener("load",a);}return b;});var Elements=this.Elements=function(a){if(a&&a.length){var e={},d; +for(var c=0;d=a[c++];){var b=Slick.uidOf(d);if(!e[b]){e[b]=true;this.push(d);}}}};Elements.prototype={length:0};Elements.parent=Array;new Type("Elements",Elements).implement({filter:function(a,b){if(!a){return this; +}return new Elements(Array.filter(this,(typeOf(a)=="string")?function(c){return c.match(a);}:a,b));}.protect(),push:function(){var d=this.length;for(var b=0,a=arguments.length; +b<a;b++){var c=document.id(arguments[b]);if(c){this[d++]=c;}}return(this.length=d);}.protect(),unshift:function(){var b=[];for(var c=0,a=arguments.length; +c<a;c++){var d=document.id(arguments[c]);if(d){b.push(d);}}return Array.prototype.unshift.apply(this,b);}.protect(),concat:function(){var b=new Elements(this); +for(var c=0,a=arguments.length;c<a;c++){var d=arguments[c];if(Type.isEnumerable(d)){b.append(d);}else{b.push(d);}}return b;}.protect(),append:function(c){for(var b=0,a=c.length; +b<a;b++){this.push(c[b]);}return this;}.protect(),empty:function(){while(this.length){delete this[--this.length];}return this;}.protect()});(function(){var f=Array.prototype.splice,a={"0":0,"1":1,length:2}; +f.call(a,1,1);if(a[1]==1){Elements.implement("splice",function(){var g=this.length;var e=f.apply(this,arguments);while(g>=this.length){delete this[g--]; +}return e;}.protect());}Array.forEachMethod(function(g,e){Elements.implement(e,g);});Array.mirror(Elements);var d;try{d=(document.createElement("<input name=x>").name=="x"); +}catch(b){}var c=function(e){return(""+e).replace(/&/g,"&").replace(/"/g,""");};Document.implement({newElement:function(e,g){if(g&&g.checked!=null){g.defaultChecked=g.checked; +}if(d&&g){e="<"+e;if(g.name){e+=' name="'+c(g.name)+'"';}if(g.type){e+=' type="'+c(g.type)+'"';}e+=">";delete g.name;delete g.type;}return this.id(this.createElement(e)).set(g); +}});})();(function(){Slick.uidOf(window);Slick.uidOf(document);Document.implement({newTextNode:function(e){return this.createTextNode(e);},getDocument:function(){return this; +},getWindow:function(){return this.window;},id:(function(){var e={string:function(L,K,l){L=Slick.find(l,"#"+L.replace(/(\W)/g,"\\$1"));return(L)?e.element(L,K):null; +},element:function(K,L){Slick.uidOf(K);if(!L&&!K.$family&&!(/^(?:object|embed)$/i).test(K.tagName)){var l=K.fireEvent;K._fireEvent=function(M,N){return l(M,N); +};Object.append(K,Element.Prototype);}return K;},object:function(K,L,l){if(K.toElement){return e.element(K.toElement(l),L);}return null;}};e.textnode=e.whitespace=e.window=e.document=function(l){return l; +};return function(K,M,L){if(K&&K.$family&&K.uniqueNumber){return K;}var l=typeOf(K);return(e[l])?e[l](K,M,L||document):null;};})()});if(window.$==null){Window.implement("$",function(e,l){return document.id(e,l,this.document); +});}Window.implement({getDocument:function(){return this.document;},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(e){return Slick.search(this,e,new Elements); +},getElement:function(e){return document.id(Slick.find(this,e));}});var p={contains:function(e){return Slick.contains(this,e);}};if(!document.contains){Document.implement(p); +}if(!document.createElement("div").contains){Element.implement(p);}var v=function(L,K){if(!L){return K;}L=Object.clone(Slick.parse(L));var l=L.expressions; +for(var e=l.length;e--;){l[e][0].combinator=K;}return L;};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(e,l){Element.implement(l,function(K){return this.getElement(v(K,e)); +});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(e,l){Element.implement(l,function(K){return this.getElements(v(K,e)); +});});Element.implement({getFirst:function(e){return document.id(Slick.search(this,v(e,">"))[0]);},getLast:function(e){return document.id(Slick.search(this,v(e,">")).getLast()); +},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(e){return document.id(Slick.find(this,"#"+(""+e).replace(/(\W)/g,"\\$1"))); +},match:function(e){return !e||Slick.match(this,e);}});if(window.$$==null){Window.implement("$$",function(e){if(arguments.length==1){if(typeof e=="string"){return Slick.search(this.document,e,new Elements); +}else{if(Type.isEnumerable(e)){return new Elements(e);}}}return new Elements(arguments);});}var A={before:function(l,e){var K=e.parentNode;if(K){K.insertBefore(l,e); +}},after:function(l,e){var K=e.parentNode;if(K){K.insertBefore(l,e.nextSibling);}},bottom:function(l,e){e.appendChild(l);},top:function(l,e){e.insertBefore(l,e.firstChild); +}};A.inside=A.bottom;var n={},d={};var o={};Array.forEach(["type","value","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","rowSpan","tabIndex","useMap"],function(e){o[e.toLowerCase()]=e; +});o.html="innerHTML";o.text=(document.createElement("div").textContent==null)?"innerText":"textContent";Object.forEach(o,function(l,e){d[e]=function(K,L){K[l]=L; +};n[e]=function(K){return K[l];};});var B=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked","autofocus","controls","autoplay","loop"]; +var k={};Array.forEach(B,function(e){var l=e.toLowerCase();k[l]=e;d[l]=function(K,L){K[e]=!!L;};n[l]=function(K){return !!K[e];};});Object.append(d,{"class":function(e,l){("className" in e)?e.className=(l||""):e.setAttribute("class",l); +},"for":function(e,l){("htmlFor" in e)?e.htmlFor=l:e.setAttribute("for",l);},style:function(e,l){(e.style)?e.style.cssText=l:e.setAttribute("style",l); +},value:function(e,l){e.value=(l!=null)?l:"";}});n["class"]=function(e){return("className" in e)?e.className||null:e.getAttribute("class");};var f=document.createElement("button"); +try{f.type="button";}catch(E){}if(f.type!="button"){d.type=function(e,l){e.setAttribute("type",l);};}f=null;var s=document.createElement("input");s.value="t"; +s.type="submit";if(s.value!="t"){d.type=function(l,e){var K=l.value;l.type=e;l.value=K;};}s=null;var u=(function(e){e.random="attribute";return(e.getAttribute("random")=="attribute"); +})(document.createElement("div"));var i=(function(e){e.innerHTML='<object><param name="should_fix" value="the unknown"></object>';return e.cloneNode(true).firstChild.childNodes.length!=1; +})(document.createElement("div"));var j=!!document.createElement("div").classList;var F=function(e){var l=(e||"").clean().split(" "),K={};return l.filter(function(L){if(L!==""&&!K[L]){return K[L]=L; +}});};var t=function(e){this.classList.add(e);};var g=function(e){this.classList.remove(e);};Element.implement({setProperty:function(l,K){var L=d[l.toLowerCase()]; +if(L){L(this,K);}else{var e;if(u){e=this.retrieve("$attributeWhiteList",{});}if(K==null){this.removeAttribute(l);if(u){delete e[l];}}else{this.setAttribute(l,""+K); +if(u){e[l]=true;}}}return this;},setProperties:function(e){for(var l in e){this.setProperty(l,e[l]);}return this;},getProperty:function(M){var K=n[M.toLowerCase()]; +if(K){return K(this);}if(u){var l=this.getAttributeNode(M),L=this.retrieve("$attributeWhiteList",{});if(!l){return null;}if(l.expando&&!L[M]){var N=this.outerHTML; +if(N.substr(0,N.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(M)<0){return null;}L[M]=true;}}var e=Slick.getAttribute(this,M);return(!e&&!Slick.hasAttribute(this,M))?null:e; +},getProperties:function(){var e=Array.from(arguments);return e.map(this.getProperty,this).associate(e);},removeProperty:function(e){return this.setProperty(e,null); +},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;},set:function(K,l){var e=Element.Properties[K];(e&&e.set)?e.set.call(this,l):this.setProperty(K,l); +}.overloadSetter(),get:function(l){var e=Element.Properties[l];return(e&&e.get)?e.get.apply(this):this.getProperty(l);}.overloadGetter(),erase:function(l){var e=Element.Properties[l]; +(e&&e.erase)?e.erase.apply(this):this.removeProperty(l);return this;},hasClass:j?function(e){return this.classList.contains(e);}:function(e){return this.className.clean().contains(e," "); +},addClass:j?function(e){F(e).forEach(t,this);return this;}:function(e){this.className=F(e+" "+this.className).join(" ");return this;},removeClass:j?function(e){F(e).forEach(g,this); +return this;}:function(e){var l=F(this.className);F(e).forEach(l.erase,l);this.className=l.join(" ");return this;},toggleClass:function(e,l){if(l==null){l=!this.hasClass(e); +}return(l)?this.addClass(e):this.removeClass(e);},adopt:function(){var L=this,e,N=Array.flatten(arguments),M=N.length;if(M>1){L=e=document.createDocumentFragment(); +}for(var K=0;K<M;K++){var l=document.id(N[K],true);if(l){L.appendChild(l);}}if(e){this.appendChild(e);}return this;},appendText:function(l,e){return this.grab(this.getDocument().newTextNode(l),e); +},grab:function(l,e){A[e||"bottom"](document.id(l,true),this);return this;},inject:function(l,e){A[e||"bottom"](this,document.id(l,true));return this;},replaces:function(e){e=document.id(e,true); +e.parentNode.replaceChild(this,e);return this;},wraps:function(l,e){l=document.id(l,true);return this.replaces(l).grab(l,e);},getSelected:function(){this.selectedIndex; +return new Elements(Array.from(this.options).filter(function(e){return e.selected;}));},toQueryString:function(){var e=[];this.getElements("input, select, textarea").each(function(K){var l=K.type; +if(!K.name||K.disabled||l=="submit"||l=="reset"||l=="file"||l=="image"){return;}var L=(K.get("tag")=="select")?K.getSelected().map(function(M){return document.id(M).get("value"); +}):((l=="radio"||l=="checkbox")&&!K.checked)?null:K.get("value");Array.from(L).each(function(M){if(typeof M!="undefined"){e.push(encodeURIComponent(K.name)+"="+encodeURIComponent(M)); +}});});return e.join("&");}});var I={before:"beforeBegin",after:"afterEnd",bottom:"beforeEnd",top:"afterBegin",inside:"beforeEnd"};Element.implement("appendHTML",("insertAdjacentHTML" in document.createElement("div"))?function(l,e){this.insertAdjacentHTML(I[e||"bottom"],l); +return this;}:function(P,M){var K=new Element("div",{html:P}),O=K.childNodes,L=K.firstChild;if(!L){return this;}if(O.length>1){L=document.createDocumentFragment(); +for(var N=0,e=O.length;N<e;N++){L.appendChild(O[N]);}}A[M||"bottom"](L,this);return this;});var m={},D={};var G=function(e){return(D[e]||(D[e]={}));};var z=function(l){var e=l.uniqueNumber; +if(l.removeEvents){l.removeEvents();}if(l.clearAttributes){l.clearAttributes();}if(e!=null){delete m[e];delete D[e];}return l;};var H={input:"checked",option:"selected",textarea:"value"}; +Element.implement({destroy:function(){var e=z(this).getElementsByTagName("*");Array.each(e,z);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose); +return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},clone:function(N,L){N=N!==false;var S=this.cloneNode(N),K=[S],M=[this],Q; +if(N){K.append(Array.from(S.getElementsByTagName("*")));M.append(Array.from(this.getElementsByTagName("*")));}for(Q=K.length;Q--;){var O=K[Q],R=M[Q];if(!L){O.removeAttribute("id"); +}if(O.clearAttributes){O.clearAttributes();O.mergeAttributes(R);O.removeAttribute("uniqueNumber");if(O.options){var V=O.options,e=R.options;for(var P=V.length; +P--;){V[P].selected=e[P].selected;}}}var l=H[R.tagName.toLowerCase()];if(l&&R[l]){O[l]=R[l];}}if(i){var T=S.getElementsByTagName("object"),U=this.getElementsByTagName("object"); +for(Q=T.length;Q--;){T[Q].outerHTML=U[Q].outerHTML;}}return document.id(S);}});[Element,Window,Document].invoke("implement",{addListener:function(l,e){if(window.attachEvent&&!window.addEventListener){m[Slick.uidOf(this)]=this; +}if(this.addEventListener){this.addEventListener(l,e,!!arguments[2]);}else{this.attachEvent("on"+l,e);}return this;},removeListener:function(l,e){if(this.removeEventListener){this.removeEventListener(l,e,!!arguments[2]); +}else{this.detachEvent("on"+l,e);}return this;},retrieve:function(l,e){var L=G(Slick.uidOf(this)),K=L[l];if(e!=null&&K==null){K=L[l]=e;}return K!=null?K:null; +},store:function(l,e){var K=G(Slick.uidOf(this));K[l]=e;return this;},eliminate:function(e){var l=G(Slick.uidOf(this));delete l[e];return this;}});if(window.attachEvent&&!window.addEventListener){var J=function(){Object.each(m,z); +if(window.CollectGarbage){CollectGarbage();}window.removeListener("unload",J);};window.addListener("unload",J);}Element.Properties={};Element.Properties.style={set:function(e){this.style.cssText=e; +},get:function(){return this.style.cssText;},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase(); +}};Element.Properties.html={set:function(e){if(e==null){e="";}else{if(typeOf(e)=="array"){e=e.join("");}}this.innerHTML=e;},erase:function(){this.innerHTML=""; +}};var a=true,h=true,C=true;var x=document.createElement("div");x.innerHTML="<nav></nav>";a=(x.childNodes.length==1);if(!a){var w="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),b=document.createDocumentFragment(),y=w.length; +while(y--){b.createElement(w[y]);}}x=null;h=Function.attempt(function(){var e=document.createElement("table");e.innerHTML="<tr><td></td></tr>";return true; +});var c=document.createElement("tr"),r="<td></td>";c.innerHTML=r;C=(c.innerHTML==r);c=null;if(!h||!C||!a){Element.Properties.html.set=(function(l){var e={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]}; +e.thead=e.tfoot=e.tbody;return function(K){var L=e[this.get("tag")];if(!L&&!a){L=[0,"",""];}if(!L){return l.call(this,K);}var O=L[0],N=document.createElement("div"),M=N; +if(!a){b.appendChild(N);}N.innerHTML=[L[1],K,L[2]].flatten().join("");while(O--){M=M.firstChild;}this.empty().adopt(M.childNodes);if(!a){b.removeChild(N); +}N=null;};})(Element.Properties.html.set);}var q=document.createElement("form");q.innerHTML="<select><option>s</option></select>";if(q.firstChild.value!="s"){Element.Properties.value={set:function(N){var l=this.get("tag"); +if(l!="select"){return this.setProperty("value",N);}var K=this.getElements("option");N=String(N);for(var L=0;L<K.length;L++){var M=K[L],e=M.getAttributeNode("value"),O=(e&&e.specified)?M.value:M.get("text"); +if(O===N){return M.selected=true;}}},get:function(){var K=this,l=K.get("tag");if(l!="select"&&l!="option"){return this.getProperty("value");}if(l=="select"&&!(K=K.getSelected()[0])){return""; +}var e=K.getAttributeNode("value");return(e&&e.specified)?K.value:K.get("text");}};}q=null;if(document.createElement("div").getAttributeNode("id")){Element.Properties.id={set:function(e){this.id=this.getAttributeNode("id").value=e; +},get:function(){return this.id||null;},erase:function(){this.id=this.getAttributeNode("id").value="";}};}})();(function(){var l=document.html,f;f=document.createElement("div"); +f.style.color="red";f.style.color=null;var e=f.style.color=="red";var k="1px solid #123abc";f.style.border=k;var o=f.style.border!=k;f=null;var n=!!window.getComputedStyle; +Element.Properties.styles={set:function(r){this.setStyles(r);}};var j=(l.style.opacity!=null),g=(l.style.filter!=null),q=/alpha\(opacity=([\d.]+)\)/i;var b=function(s,r){s.store("$opacity",r); +s.style.visibility=r>0||r==null?"visible":"hidden";};var p=function(r,v,u){var t=r.style,s=t.filter||r.getComputedStyle("filter")||"";t.filter=(v.test(s)?s.replace(v,u):s+" "+u).trim(); +if(!t.filter){t.removeAttribute("filter");}};var h=(j?function(s,r){s.style.opacity=r;}:(g?function(s,r){if(!s.currentStyle||!s.currentStyle.hasLayout){s.style.zoom=1; +}if(r==null||r==1){p(s,q,"");if(r==1&&i(s)!=1){p(s,q,"alpha(opacity=100)");}}else{p(s,q,"alpha(opacity="+(r*100).limit(0,100).round()+")");}}:b));var i=(j?function(s){var r=s.style.opacity||s.getComputedStyle("opacity"); +return(r=="")?1:r.toFloat();}:(g?function(s){var t=(s.style.filter||s.getComputedStyle("filter")),r;if(t){r=t.match(q);}return(r==null||t==null)?1:(r[1]/100); +}:function(s){var r=s.retrieve("$opacity");if(r==null){r=(s.style.visibility=="hidden"?0:1);}return r;}));var d=(l.style.cssFloat==null)?"styleFloat":"cssFloat",a={left:"0%",top:"0%",center:"50%",right:"100%",bottom:"100%"},c=(l.style.backgroundPositionX!=null); +var m=function(r,s){if(s=="backgroundPosition"){r.removeAttribute(s+"X");s+="Y";}r.removeAttribute(s);};Element.implement({getComputedStyle:function(t){if(!n&&this.currentStyle){return this.currentStyle[t.camelCase()]; +}var s=Element.getDocument(this).defaultView,r=s?s.getComputedStyle(this,null):null;return(r)?r.getPropertyValue((t==d)?"float":t.hyphenate()):"";},setStyle:function(s,r){if(s=="opacity"){if(r!=null){r=parseFloat(r); +}h(this,r);return this;}s=(s=="float"?d:s).camelCase();if(typeOf(r)!="string"){var t=(Element.Styles[s]||"@").split(" ");r=Array.from(r).map(function(v,u){if(!t[u]){return""; +}return(typeOf(v)=="number")?t[u].replace("@",Math.round(v)):v;}).join(" ");}else{if(r==String(Number(r))){r=Math.round(r);}}this.style[s]=r;if((r==""||r==null)&&e&&this.style.removeAttribute){m(this.style,s); +}return this;},getStyle:function(x){if(x=="opacity"){return i(this);}x=(x=="float"?d:x).camelCase();var r=this.style[x];if(!r||x=="zIndex"){if(Element.ShortStyles.hasOwnProperty(x)){r=[]; +for(var w in Element.ShortStyles[x]){r.push(this.getStyle(w));}return r.join(" ");}r=this.getComputedStyle(x);}if(c&&/^backgroundPosition[XY]?$/.test(x)){return r.replace(/(top|right|bottom|left)/g,function(s){return a[s]; +})||"0px";}if(!r&&x=="backgroundPosition"){return"0px 0px";}if(r){r=String(r);var u=r.match(/rgba?\([\d\s,]+\)/);if(u){r=r.replace(u[0],u[0].rgbToHex()); +}}if(!n&&!this.style[x]){if((/^(height|width)$/).test(x)&&!(/px$/.test(r))){var t=(x=="width")?["left","right"]:["top","bottom"],v=0;t.each(function(s){v+=this.getStyle("border-"+s+"-width").toInt()+this.getStyle("padding-"+s).toInt(); +},this);return this["offset"+x.capitalize()]-v+"px";}if((/^border(.+)Width|margin|padding/).test(x)&&isNaN(parseFloat(r))){return"0px";}}if(o&&/^border(Top|Right|Bottom|Left)?$/.test(x)&&/^#/.test(r)){return r.replace(/^(.+)\s(.+)\s(.+)$/,"$2 $3 $1"); +}return r;},setStyles:function(s){for(var r in s){this.setStyle(r,s[r]);}return this;},getStyles:function(){var r={};Array.flatten(arguments).each(function(s){r[s]=this.getStyle(s); +},this);return r;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundSize:"@px",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"}; +Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(x){var w=Element.ShortStyles; +var s=Element.Styles;["margin","padding"].each(function(y){var z=y+x;w[y][z]=s[z]="@px";});var v="border"+x;w.border[v]=s[v]="@px @ rgb(@, @, @)";var u=v+"Width",r=v+"Style",t=v+"Color"; +w[v]={};w.borderWidth[u]=w[v][u]=s[u]="@px";w.borderStyle[r]=w[v][r]=s[r]="@";w.borderColor[t]=w[v][t]=s[t]="rgb(@, @, @)";});if(c){Element.ShortStyles.backgroundPosition={backgroundPositionX:"@",backgroundPositionY:"@"}; +}})();(function(){Element.Properties.events={set:function(b){this.addEvents(b);}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{}); +if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this;}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f); +}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k);}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j); +};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow());if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]); +}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events");if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d); +if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e];if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e); +}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this; +},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);}return this;}var c=this.retrieve("events");if(!c){return this; +}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);},this);delete c[b]; +}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c); +}else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b); +}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,hashchange:1,popstate:2,error:1,abort:1,scroll:1}; +Element.Events={mousewheel:{base:"onwheel" in document?"wheel":"onmousewheel" in document?"mousewheel":"DOMMouseScroll"}};var a=function(b){var c=b.relatedTarget; +if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c));};if("onmouseenter" in document.documentElement){Element.NativeEvents.mouseenter=Element.NativeEvents.mouseleave=2; +Element.MouseenterCheck=a;}else{Element.Events.mouseenter={base:"mouseover",condition:a};Element.Events.mouseleave={base:"mouseout",condition:a};}if(!window.addEventListener){Element.NativeEvents.propertychange=2; +Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change";},condition:function(b){return b.type!="propertychange"||b.event.propertyName=="checked"; +}};}})();(function(){var c=!!window.addEventListener;Element.NativeEvents.focusin=Element.NativeEvents.focusout=2;var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p); +}p=document.id(p.parentNode);}};var a={mouseenter:{base:"mouseover",condition:Element.MouseenterCheck},mouseleave:{base:"mouseout",condition:Element.MouseenterCheck},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}}; +var b="$delegation:";var i=function(l){return{base:"focusin",remove:function(m,o){var p=m.retrieve(b+l+"listeners",{})[o];if(p&&p.forms){for(var n=p.forms.length; +n--;){p.forms[n].removeEvent(l,p.fns[n]);}}},listen:function(x,r,v,n,t,s){var o=(t.get("tag")=="form")?t:n.target.getParent("form");if(!o){return;}var u=x.retrieve(b+l+"listeners",{}),p=u[s]||{forms:[],fns:[]},m=p.forms,w=p.fns; +if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEvent(l,q);w.push(q);u[s]=p;x.store(b+l+"listeners",u);}};};var d=function(l){return{base:"focusin",listen:function(m,n,p,q,r){var o={blur:function(){this.removeEvents(o); +}};o[l]=function(s){k(m,n,p,s,r);};q.target.addEvents(o);}};};if(!c){Object.append(a,{submit:i("submit"),reset:i("reset"),change:d("change"),select:d("select")}); +}var h=Element.prototype,f=h.addEvent,j=h.removeEvent;var e=function(l,m){return function(r,q,n){if(r.indexOf(":relay")==-1){return l.call(this,r,q,n); +}var o=Slick.parse(r).expressions[0][0];if(o.pseudos[0].key!="relay"){return l.call(this,r,q,n);}var p=o.tag;o.pseudos.slice(1).each(function(s){p+=":"+s.key+(s.value?"("+s.value+")":""); +});l.call(this,r,q);return m.call(this,p,o.pseudos[0].value,q);};};var g={addEvent:function(v,q,x){var t=this.retrieve("$delegates",{}),r=t[v];if(r){for(var y in r){if(r[y].fn==x&&r[y].match==q){return this; +}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(n.condition||w&&w.condition){var l=q,m=n.condition||w.condition; +q=function(C,B){return l(C,B)&&m.call(C,B,v);};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s); +}}:function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture); +},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r];if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u); +}delete p[u];q[m]=p;return j.call(this,r,w,l.capture);}var o,v;if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o); +}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o);}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)}); +})();(function(){var h=document.createElement("div"),e=document.createElement("div");h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null; +var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName);};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n); +}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize();}return{x:this.offsetWidth,y:this.offsetHeight}; +},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};},getScroll:function(){if(a(this)){return this.getWindow().getScroll(); +}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0};while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop; +n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}var n=(k(m,"position")=="static")?i:l; +while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}try{return m.offsetParent; +}catch(n){}return null;},getOffsets:function(){var n=this.getBoundingClientRect;if(n){var r=this.getBoundingClientRect(),p=document.id(this.getDocument().documentElement),q=p.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed"); +return{x:r.left.toInt()+t.x+((s)?0:q.x)-p.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-p.clientTop};}var o=this,m={x:0,y:0};if(a(this)){return m;}while(o&&!a(o)){m.x+=o.offsetLeft; +m.y+=o.offsetTop;o=o.offsetParent;}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls();var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition(); +return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates();}var m=this.getPosition(o),n=this.getSize(); +var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")}; +},setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight}; +},getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body; +return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize(); +return{top:0,left:0,bottom:m.y,right:m.x,height:m.y,width:m.x};}});var k=Element.getComputedStyle;function j(m,n){return k(m,n).toInt()||0;}function c(m){return k(m,"-moz-box-sizing")=="border-box"; +}function g(m){return j(m,"border-top-width");}function b(m){return j(m,"border-left-width");}function a(m){return(/^(?:body|html)$/i).test(m.tagName); +}function f(m){var n=m.getDocument();return(!n.compatMode||n.compatMode=="CSS1Compat")?n.html:n.body;}})();Element.alias({position:"setPosition"});[Window,Document,Element].invoke("implement",{getHeight:function(){return this.getSize().y; +},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x; +},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y; +},getLeft:function(){return this.getPosition().x;}});(function(){var f=this.Fx=new Class({Implements:[Chain,Events,Options],options:{fps:60,unit:false,duration:500,frames:null,frameSkip:true,link:"ignore"},initialize:function(g){this.subject=this.subject||this; +this.setOptions(g);},getTransition:function(){return function(g){return -(Math.cos(Math.PI*g)-1)/2;};},step:function(g){if(this.options.frameSkip){var h=(this.time!=null)?(g-this.time):0,i=h/this.frameInterval; +this.time=g;this.frame+=i;}else{this.frame++;}if(this.frame<this.frames){var j=this.transition(this.frame/this.frames);this.set(this.compute(this.from,this.to,j)); +}else{this.frame=this.frames;this.set(this.compute(this.from,this.to,1));this.stop();}},set:function(g){return g;},compute:function(i,h,g){return f.compute(i,h,g); +},check:function(){if(!this.isRunning()){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this)); +return false;}return false;},start:function(k,j){if(!this.check(k,j)){return this;}this.from=k;this.to=j;this.frame=(this.options.frameSkip)?0:-1;this.time=null; +this.transition=this.getTransition();var i=this.options.frames,h=this.options.fps,g=this.options.duration;this.duration=f.Durations[g]||g.toInt();this.frameInterval=1000/h; +this.frames=i||Math.round(this.duration/this.frameInterval);this.fireEvent("start",this.subject);b.call(this,h);return this;},stop:function(){if(this.isRunning()){this.time=null; +d.call(this,this.options.fps);if(this.frames==this.frame){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject); +}}else{this.fireEvent("stop",this.subject);}}return this;},cancel:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);this.frame=this.frames; +this.fireEvent("cancel",this.subject).clearChain();}return this;},pause:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);}return this; +},resume:function(){if(this.isPaused()){b.call(this,this.options.fps);}return this;},isRunning:function(){var g=e[this.options.fps];return g&&g.contains(this); +},isPaused:function(){return(this.frame<this.frames)&&!this.isRunning();}});f.compute=function(i,h,g){return(h-i)*g+i;};f.Durations={"short":250,normal:500,"long":1000}; +var e={},c={};var a=function(){var h=Date.now();for(var j=this.length;j--;){var g=this[j];if(g){g.step(h);}}};var b=function(h){var g=e[h]||(e[h]=[]);g.push(this); +if(!c[h]){c[h]=a.periodical(Math.round(1000/h),g);}};var d=function(h){var g=e[h];if(g){g.erase(this);if(!g.length&&c[h]){delete e[h];c[h]=clearInterval(c[h]); +}}};})();Fx.CSS=new Class({Extends:Fx,prepare:function(b,e,a){a=Array.from(a);var h=a[0],g=a[1];if(g==null){g=h;h=b.getStyle(e);var c=this.options.unit; +if(c&&h&&typeof h=="string"&&h.slice(-c.length)!=c&&parseFloat(h)!=0){b.setStyle(e,g+c);var d=b.getComputedStyle(e);if(!(/px$/.test(d))){d=b.style[("pixel-"+e).camelCase()]; +if(d==null){var f=b.style.left;b.style.left=g+c;d=b.style.pixelLeft;b.style.left=f;}}h=(g||1)/(parseFloat(d)||1)*(parseFloat(h)||0);b.setStyle(e,h+c);}}return{from:this.parse(h),to:this.parse(g)}; +},parse:function(a){a=Function.from(a)();a=(typeof a=="string")?a.split(" "):Array.from(a);return a.map(function(c){c=String(c);var b=false;Object.each(Fx.CSS.Parsers,function(f,e){if(b){return; +}var d=f.parse(c);if(d||d===0){b={value:d,parser:f};}});b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser}); +});a.$family=Function.from("fx:css:value");return a;},serve:function(c,b){if(typeOf(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b)); +});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var d={},c=new RegExp("^"+a.escapeRegExp()+"$"); +var b=function(e){Array.each(e,function(h,f){if(h.media){b(h.rules||h.cssRules);return;}if(!h.style){return;}var g=(h.selectorText)?h.selectorText.replace(/^\w+/,function(i){return i.toLowerCase(); +}):null;if(!g||!c.test(g)){return;}Object.each(Element.Styles,function(j,i){if(!h.style[i]||Element.ShortStyles[i]){return;}j=String(h.style[i]);d[i]=((/^rgb/).test(j))?j.rgbToHex():j; +});});};Array.each(document.styleSheets,function(g,f){var e=g.href;if(e&&e.indexOf("://")>-1&&e.indexOf(document.domain)==-1){return;}var h=g.rules||g.cssRules; +b(h);});return Fx.CSS.Cache[a]=d;}});Fx.CSS.Cache={};Fx.CSS.Parsers={Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true); +}return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a)); +});},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:Function.from(false),compute:function(b,a){return a; +},serve:function(a){return a;}}};Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);},set:function(b,a){if(arguments.length==1){a=b; +b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this; +}var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);return this.parent(a.from,a.to); +}});Element.Properties.tween={set:function(a){this.get("tween").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("tween");if(!a){a=new Fx.Tween(this,{link:"cancel"}); +this.store("tween",a);}return a;}};Element.implement({tween:function(a,c,b){this.get("tween").start(a,c,b);return this;},fade:function(d){var e=this.get("tween"),g,c=["opacity"].append(arguments),a; +if(c[1]==null){c[1]="toggle";}switch(c[1]){case"in":g="start";c[1]=1;break;case"out":g="start";c[1]=0;break;case"show":g="set";c[1]=1;break;case"hide":g="set"; +c[1]=0;break;case"toggle":var b=this.retrieve("fade:flag",this.getStyle("opacity")==1);g="start";c[1]=b?0:1;this.store("fade:flag",!b);a=true;break;default:g="start"; +}if(!a){this.eliminate("fade:flag");}e[g].apply(e,c);var f=c[c.length-1];if(g=="set"||f!=0){this.setStyle("visibility",f==0?"hidden":"visible");}else{e.chain(function(){this.element.setStyle("visibility","hidden"); +this.callChain();});}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));a=(a=="transparent")?"#fff":a; +}var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original")); +b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a); +},set:function(a){if(typeof a=="string"){a=this.search(a);}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={}; +for(var b in e){a[b]=this.parent(e[b],d[b],c);}return a;},start:function(b){if(!this.check(b)){return this;}if(typeof b=="string"){b=this.search(b);}var e={},d={}; +for(var c in b){var a=this.prepare(this.element,c,b[c]);e[c]=a.from;d[c]=a.to;}return this.parent(e,d);}});Element.Properties.morph={set:function(a){this.get("morph").cancel().setOptions(a); +return this;},get:function(){var a=this.retrieve("morph");if(!a){a=new Fx.Morph(this,{link:"cancel"});this.store("morph",a);}return a;}};Element.implement({morph:function(a){this.get("morph").start(a); +return this;}});Fx.implement({getTransition:function(){var a=this.options.transition||Fx.Transitions.Sine.easeInOut;if(typeof a=="string"){var b=a.split(":"); +a=Fx.Transitions;a=a[b[0]]||a[b[0].capitalize()];if(b[1]){a=a["ease"+b[1].capitalize()+(b[2]?b[2].capitalize():"")];}}return a;}});Fx.Transition=function(c,b){b=Array.from(b); +var a=function(d){return c(d,b);};return Object.append(a,{easeIn:a,easeOut:function(d){return 1-c(1-d,b);},easeInOut:function(d){return(d<=0.5?c(2*d,b):(2-c(2*(1-d),b)))/2; +}});};Fx.Transitions={linear:function(a){return a;}};Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);}};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a&&a[0]||6); +},Expo:function(a){return Math.pow(2,8*(a-1));},Circ:function(a){return 1-Math.sin(Math.acos(a));},Sine:function(a){return 1-Math.cos(a*Math.PI/2);},Back:function(b,a){a=a&&a[0]||1.618; +return Math.pow(b,2)*((a+1)*b-a);},Bounce:function(f){var e;for(var d=0,c=1;1;d+=c,c/=2){if(f>=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);break;}}return e; +},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a&&a[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,a+2); +});});(function(){var d=function(){},a=("onprogress" in new Browser.Request);var c=this.Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,timeout:0,noCache:false},initialize:function(e){this.xhr=new Browser.Request(); +this.setOptions(e);this.headers=this.options.headers;},onStateChange:function(){var e=this.xhr;if(e.readyState!=4||!this.running){return;}this.running=false; +this.status=0;Function.attempt(function(){var f=e.status;this.status=(f==1223)?204:f;}.bind(this));e.onreadystatechange=d;if(a){e.onprogress=e.onloadstart=d; +}clearTimeout(this.timer);this.response={text:this.xhr.responseText||"",xml:this.xhr.responseXML};if(this.options.isSuccess.call(this,this.status)){this.success(this.response.text,this.response.xml); +}else{this.failure();}},isSuccess:function(){var e=this.status;return(e>=200&&e<300);},isRunning:function(){return !!this.running;},processScripts:function(e){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return Browser.exec(e); +}return e.stripScripts(this.options.evalScripts);},success:function(f,e){this.onSuccess(this.processScripts(f),e);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain(); +},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},loadstart:function(e){this.fireEvent("loadstart",[e,this.xhr]); +},progress:function(e){this.fireEvent("progress",[e,this.xhr]);},timeout:function(){this.fireEvent("timeout",this.xhr);},setHeader:function(e,f){this.headers[e]=f; +return this;},getHeader:function(e){return Function.attempt(function(){return this.xhr.getResponseHeader(e);}.bind(this));},check:function(){if(!this.running){return true; +}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));return false;}return false;},send:function(o){if(!this.check(o)){return this; +}this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.running=true;var l=typeOf(o);if(l=="string"||l=="element"){o={data:o};}var h=this.options; +o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString(); +break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e; +j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g; +}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.indexOf("?")>-1?"&":"?")+String.uniqueID(); +}if(j&&(e=="get"||e=="delete")){f+=(f.indexOf("?")>-1?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this); +}n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true; +}n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]); +}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}else{if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this); +}}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d; +if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e}; +if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e); +return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")}); +this.store("send",e);}return e;}};Element.implement({send:function(e){var f=this.get("send");f.send({data:this,url:e||f.options.url});return this;}});})(); +Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false,headers:{Accept:"text/html, application/xml, text/xml, */*"}},success:function(f){var e=this.options,c=this.response; +c.html=f.stripScripts(function(h){c.javascript=h;});var d=c.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);if(d){c.html=d[1];}var b=new Element("div").set("html",c.html); +c.tree=b.childNodes;c.elements=b.getElements(e.filter||"*");if(e.filter){c.tree=c.elements;}if(e.update){var g=document.id(e.update).empty();if(e.filter){g.adopt(c.elements); +}else{g.set("html",c.html);}}else{if(e.append){var a=document.id(e.append);if(e.filter){c.elements.reverse().inject(a);}else{a.adopt(b.getChildren());}}}if(e.evalScripts){Browser.exec(c.javascript); +}this.onSuccess(c.tree,c.elements,c.html,c.javascript);}});Element.Properties.load={set:function(a){var b=this.get("load").cancel();b.setOptions(a);return this; +},get:function(){var a=this.retrieve("load");if(!a){a=new Request.HTML({data:this,link:"cancel",update:this,method:"get"});this.store("load",a);}return a; +}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Type.isObject,url:Type.isString}));return this;}});if(typeof JSON=="undefined"){this.JSON={}; +}(function(){var special={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};var escape=function(chr){return special[chr]||"\\u"+("0000"+chr.charCodeAt(0).toString(16)).slice(-4); +};JSON.validate=function(string){string=string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""); +return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON(); +}switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[]; +Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj; +case"null":return"null";}return null;};JSON.secure=true;JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure==null){secure=JSON.secure; +}if(secure){if(JSON.parse){return JSON.parse(string);}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure."); +}}return eval("("+string+")");};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"}); +},success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure(); +}else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b; +this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path; +}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure"; +}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)"); +return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,Object.merge({},this.options,{duration:-1})).write("");return this;}}); +Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose(); +};(function(i,k){var l,f,e=[],c,b,d=k.createElement("div");var g=function(){clearTimeout(b);if(l){return;}Browser.loaded=l=true;k.removeListener("DOMContentLoaded",g).removeListener("readystatechange",a); +k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.length;m--;){if(e[m]()){g();return true;}}return false;};var j=function(){clearTimeout(b); +if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h); +c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a); +}else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this); +}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);
\ No newline at end of file diff --git a/module/webui/themes/flat/js/static/mootools-more.js b/module/webui/themes/flat/js/static/mootools-more.js new file mode 100644 index 000000000..c7f4a1a0e --- /dev/null +++ b/module/webui/themes/flat/js/static/mootools-more.js @@ -0,0 +1,2856 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/more/c1cc18c2fff04bcc58921b4dff80a6f1 + +packager build: + - packager build More/Form.Request More/Fx.Reveal More/Sortables More/Request.Periodical More/Color + +... +*/ + +/* +--- + +script: More.js + +name: More + +description: MooTools More + +license: MIT-style license + +authors: + - Guillermo Rauch + - Thomas Aylott + - Scott Kyle + - Arian Stolwijk + - Tim Wienk + - Christoph Pojer + - Aaron Newton + - Jacob Thornton + +requires: + - Core/MooTools + +provides: [MooTools.More] + +... +*/ + +MooTools.More = { + version: '1.5.0', + build: '73db5e24e6e9c5c87b3a27aebef2248053f7db37' +}; + + +/* +--- + +script: Class.Binds.js + +name: Class.Binds + +description: Automagically binds specified methods in a class to the instance of the class. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - MooTools.More + +provides: [Class.Binds] + +... +*/ + +Class.Mutators.Binds = function(binds){ + if (!this.prototype.initialize) this.implement('initialize', function(){}); + return Array.from(binds).concat(this.prototype.Binds || []); +}; + +Class.Mutators.initialize = function(initialize){ + return function(){ + Array.from(this.Binds).each(function(name){ + var original = this[name]; + if (original) this[name] = original.bind(this); + }, this); + return initialize.apply(this, arguments); + }; +}; + + +/* +--- + +script: Class.Occlude.js + +name: Class.Occlude + +description: Prevents a class from being applied to a DOM element twice. + +license: MIT-style license. + +authors: + - Aaron Newton + +requires: + - Core/Class + - Core/Element + - MooTools.More + +provides: [Class.Occlude] + +... +*/ + +Class.Occlude = new Class({ + + occlude: function(property, element){ + element = document.id(element || this.element); + var instance = element.retrieve(property || this.property); + if (instance && !this.occluded) + return (this.occluded = instance); + + this.occluded = false; + element.store(property || this.property, this); + return this.occluded; + } + +}); + + +/* +--- + +script: Class.Refactor.js + +name: Class.Refactor + +description: Extends a class onto itself with new property, preserving any items attached to the class's namespace. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - MooTools.More + +# Some modules declare themselves dependent on Class.Refactor +provides: [Class.refactor, Class.Refactor] + +... +*/ + +Class.refactor = function(original, refactors){ + + Object.each(refactors, function(item, name){ + var origin = original.prototype[name]; + origin = (origin && origin.$origin) || origin || function(){}; + original.implement(name, (typeof item == 'function') ? function(){ + var old = this.previous; + this.previous = origin; + var value = item.apply(this, arguments); + this.previous = old; + return value; + } : item); + }); + + return original; + +}; + + +/* +--- + +script: Element.Measure.js + +name: Element.Measure + +description: Extends the Element native object to include methods useful in measuring dimensions. + +credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz" + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - Core/Element.Dimensions + - MooTools.More + +provides: [Element.Measure] + +... +*/ + +(function(){ + +var getStylesList = function(styles, planes){ + var list = []; + Object.each(planes, function(directions){ + Object.each(directions, function(edge){ + styles.each(function(style){ + list.push(style + '-' + edge + (style == 'border' ? '-width' : '')); + }); + }); + }); + return list; +}; + +var calculateEdgeSize = function(edge, styles){ + var total = 0; + Object.each(styles, function(value, style){ + if (style.test(edge)) total = total + value.toInt(); + }); + return total; +}; + +var isVisible = function(el){ + return !!(!el || el.offsetHeight || el.offsetWidth); +}; + + +Element.implement({ + + measure: function(fn){ + if (isVisible(this)) return fn.call(this); + var parent = this.getParent(), + toMeasure = []; + while (!isVisible(parent) && parent != document.body){ + toMeasure.push(parent.expose()); + parent = parent.getParent(); + } + var restore = this.expose(), + result = fn.call(this); + restore(); + toMeasure.each(function(restore){ + restore(); + }); + return result; + }, + + expose: function(){ + if (this.getStyle('display') != 'none') return function(){}; + var before = this.style.cssText; + this.setStyles({ + display: 'block', + position: 'absolute', + visibility: 'hidden' + }); + return function(){ + this.style.cssText = before; + }.bind(this); + }, + + getDimensions: function(options){ + options = Object.merge({computeSize: false}, options); + var dim = {x: 0, y: 0}; + + var getSize = function(el, options){ + return (options.computeSize) ? el.getComputedSize(options) : el.getSize(); + }; + + var parent = this.getParent('body'); + + if (parent && this.getStyle('display') == 'none'){ + dim = this.measure(function(){ + return getSize(this, options); + }); + } else if (parent){ + try { //safari sometimes crashes here, so catch it + dim = getSize(this, options); + }catch(e){} + } + + return Object.append(dim, (dim.x || dim.x === 0) ? { + width: dim.x, + height: dim.y + } : { + x: dim.width, + y: dim.height + } + ); + }, + + getComputedSize: function(options){ + + + options = Object.merge({ + styles: ['padding','border'], + planes: { + height: ['top','bottom'], + width: ['left','right'] + }, + mode: 'both' + }, options); + + var styles = {}, + size = {width: 0, height: 0}, + dimensions; + + if (options.mode == 'vertical'){ + delete size.width; + delete options.planes.width; + } else if (options.mode == 'horizontal'){ + delete size.height; + delete options.planes.height; + } + + getStylesList(options.styles, options.planes).each(function(style){ + styles[style] = this.getStyle(style).toInt(); + }, this); + + Object.each(options.planes, function(edges, plane){ + + var capitalized = plane.capitalize(), + style = this.getStyle(plane); + + if (style == 'auto' && !dimensions) dimensions = this.getDimensions(); + + style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt(); + size['total' + capitalized] = style; + + edges.each(function(edge){ + var edgesize = calculateEdgeSize(edge, styles); + size['computed' + edge.capitalize()] = edgesize; + size['total' + capitalized] += edgesize; + }); + + }, this); + + return Object.append(size, styles); + } + +}); + +})(); + + +/* +--- + +script: Element.Position.js + +name: Element.Position + +description: Extends the Element native object to include methods useful positioning elements relative to others. + +license: MIT-style license + +authors: + - Aaron Newton + - Jacob Thornton + +requires: + - Core/Options + - Core/Element.Dimensions + - Element.Measure + +provides: [Element.Position] + +... +*/ + +(function(original){ + +var local = Element.Position = { + + options: {/* + edge: false, + returnPos: false, + minimum: {x: 0, y: 0}, + maximum: {x: 0, y: 0}, + relFixedPosition: false, + ignoreMargins: false, + ignoreScroll: false, + allowNegative: false,*/ + relativeTo: document.body, + position: { + x: 'center', //left, center, right + y: 'center' //top, center, bottom + }, + offset: {x: 0, y: 0} + }, + + getOptions: function(element, options){ + options = Object.merge({}, local.options, options); + local.setPositionOption(options); + local.setEdgeOption(options); + local.setOffsetOption(element, options); + local.setDimensionsOption(element, options); + return options; + }, + + setPositionOption: function(options){ + options.position = local.getCoordinateFromValue(options.position); + }, + + setEdgeOption: function(options){ + var edgeOption = local.getCoordinateFromValue(options.edge); + options.edge = edgeOption ? edgeOption : + (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} : + {x: 'left', y: 'top'}; + }, + + setOffsetOption: function(element, options){ + var parentOffset = {x: 0, y: 0}; + var parentScroll = {x: 0, y: 0}; + var offsetParent = element.measure(function(){ + return document.id(this.getOffsetParent()); + }); + + if (!offsetParent || offsetParent == element.getDocument().body) return; + + parentScroll = offsetParent.getScroll(); + parentOffset = offsetParent.measure(function(){ + var position = this.getPosition(); + if (this.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.x += scroll.x; + position.y += scroll.y; + } + return position; + }); + + options.offset = { + parentPositioned: offsetParent != document.id(options.relativeTo), + x: options.offset.x - parentOffset.x + parentScroll.x, + y: options.offset.y - parentOffset.y + parentScroll.y + }; + }, + + setDimensionsOption: function(element, options){ + options.dimensions = element.getDimensions({ + computeSize: true, + styles: ['padding', 'border', 'margin'] + }); + }, + + getPosition: function(element, options){ + var position = {}; + options = local.getOptions(element, options); + var relativeTo = document.id(options.relativeTo) || document.body; + + local.setPositionCoordinates(options, position, relativeTo); + if (options.edge) local.toEdge(position, options); + + var offset = options.offset; + position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt(); + position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt(); + + local.toMinMax(position, options); + + if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position); + if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position); + if (options.ignoreMargins) local.toIgnoreMargins(position, options); + + position.left = Math.ceil(position.left); + position.top = Math.ceil(position.top); + delete position.x; + delete position.y; + + return position; + }, + + setPositionCoordinates: function(options, position, relativeTo){ + var offsetY = options.offset.y, + offsetX = options.offset.x, + calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(), + top = calc.y, + left = calc.x, + winSize = window.getSize(); + + switch(options.position.x){ + case 'left': position.x = left + offsetX; break; + case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break; + default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break; + } + + switch(options.position.y){ + case 'top': position.y = top + offsetY; break; + case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break; + default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break; + } + }, + + toMinMax: function(position, options){ + var xy = {left: 'x', top: 'y'}, value; + ['minimum', 'maximum'].each(function(minmax){ + ['left', 'top'].each(function(lr){ + value = options[minmax] ? options[minmax][xy[lr]] : null; + if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value; + }); + }); + }, + + toRelFixedPosition: function(relativeTo, position){ + var winScroll = window.getScroll(); + position.top += winScroll.y; + position.left += winScroll.x; + }, + + toIgnoreScroll: function(relativeTo, position){ + var relScroll = relativeTo.getScroll(); + position.top -= relScroll.y; + position.left -= relScroll.x; + }, + + toIgnoreMargins: function(position, options){ + position.left += options.edge.x == 'right' + ? options.dimensions['margin-right'] + : (options.edge.x != 'center' + ? -options.dimensions['margin-left'] + : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2)); + + position.top += options.edge.y == 'bottom' + ? options.dimensions['margin-bottom'] + : (options.edge.y != 'center' + ? -options.dimensions['margin-top'] + : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2)); + }, + + toEdge: function(position, options){ + var edgeOffset = {}, + dimensions = options.dimensions, + edge = options.edge; + + switch(edge.x){ + case 'left': edgeOffset.x = 0; break; + case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break; + // center + default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break; + } + + switch(edge.y){ + case 'top': edgeOffset.y = 0; break; + case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break; + // center + default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break; + } + + position.x += edgeOffset.x; + position.y += edgeOffset.y; + }, + + getCoordinateFromValue: function(option){ + if (typeOf(option) != 'string') return option; + option = option.toLowerCase(); + + return { + x: option.test('left') ? 'left' + : (option.test('right') ? 'right' : 'center'), + y: option.test(/upper|top/) ? 'top' + : (option.test('bottom') ? 'bottom' : 'center') + }; + } + +}; + +Element.implement({ + + position: function(options){ + if (options && (options.x != null || options.y != null)){ + return (original ? original.apply(this, arguments) : this); + } + var position = this.setStyle('position', 'absolute').calculatePosition(options); + return (options && options.returnPos) ? position : this.setStyles(position); + }, + + calculatePosition: function(options){ + return local.getPosition(this, options); + } + +}); + +})(Element.prototype.position); + + +/* +--- + +script: IframeShim.js + +name: IframeShim + +description: Defines IframeShim, a class for obscuring select lists and flash objects in IE. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Event + - Core/Element.Style + - Core/Options + - Core/Events + - Element.Position + - Class.Occlude + +provides: [IframeShim] + +... +*/ + +(function(){ + +var browsers = false; + + +this.IframeShim = new Class({ + + Implements: [Options, Events, Class.Occlude], + + options: { + className: 'iframeShim', + src: 'javascript:false;document.write("");', + display: false, + zIndex: null, + margin: 0, + offset: {x: 0, y: 0}, + browsers: browsers + }, + + property: 'IframeShim', + + initialize: function(element, options){ + this.element = document.id(element); + if (this.occlude()) return this.occluded; + this.setOptions(options); + this.makeShim(); + return this; + }, + + makeShim: function(){ + if (this.options.browsers){ + var zIndex = this.element.getStyle('zIndex').toInt(); + + if (!zIndex){ + zIndex = 1; + var pos = this.element.getStyle('position'); + if (pos == 'static' || !pos) this.element.setStyle('position', 'relative'); + this.element.setStyle('zIndex', zIndex); + } + zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1; + if (zIndex < 0) zIndex = 1; + this.shim = new Element('iframe', { + src: this.options.src, + scrolling: 'no', + frameborder: 0, + styles: { + zIndex: zIndex, + position: 'absolute', + border: 'none', + filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)' + }, + 'class': this.options.className + }).store('IframeShim', this); + var inject = (function(){ + this.shim.inject(this.element, 'after'); + this[this.options.display ? 'show' : 'hide'](); + this.fireEvent('inject'); + }).bind(this); + if (!IframeShim.ready) window.addEvent('load', inject); + else inject(); + } else { + this.position = this.hide = this.show = this.dispose = Function.from(this); + } + }, + + position: function(){ + if (!IframeShim.ready || !this.shim) return this; + var size = this.element.measure(function(){ + return this.getSize(); + }); + if (this.options.margin != undefined){ + size.x = size.x - (this.options.margin * 2); + size.y = size.y - (this.options.margin * 2); + this.options.offset.x += this.options.margin; + this.options.offset.y += this.options.margin; + } + this.shim.set({width: size.x, height: size.y}).position({ + relativeTo: this.element, + offset: this.options.offset + }); + return this; + }, + + hide: function(){ + if (this.shim) this.shim.setStyle('display', 'none'); + return this; + }, + + show: function(){ + if (this.shim) this.shim.setStyle('display', 'block'); + return this.position(); + }, + + dispose: function(){ + if (this.shim) this.shim.dispose(); + return this; + }, + + destroy: function(){ + if (this.shim) this.shim.destroy(); + return this; + } + +}); + +})(); + +window.addEvent('load', function(){ + IframeShim.ready = true; +}); + + +/* +--- + +script: Mask.js + +name: Mask + +description: Creates a mask element to cover another. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Options + - Core/Events + - Core/Element.Event + - Class.Binds + - Element.Position + - IframeShim + +provides: [Mask] + +... +*/ + +var Mask = new Class({ + + Implements: [Options, Events], + + Binds: ['position'], + + options: {/* + onShow: function(){}, + onHide: function(){}, + onDestroy: function(){}, + onClick: function(event){}, + inject: { + where: 'after', + target: null, + }, + hideOnClick: false, + id: null, + destroyOnHide: false,*/ + style: {}, + 'class': 'mask', + maskMargins: false, + useIframeShim: true, + iframeShimOptions: {} + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('mask', this); + this.setOptions(options); + this.render(); + this.inject(); + }, + + render: function(){ + this.element = new Element('div', { + 'class': this.options['class'], + id: this.options.id || 'mask-' + String.uniqueID(), + styles: Object.merge({}, this.options.style, { + display: 'none' + }), + events: { + click: function(event){ + this.fireEvent('click', event); + if (this.options.hideOnClick) this.hide(); + }.bind(this) + } + }); + + this.hidden = true; + }, + + toElement: function(){ + return this.element; + }, + + inject: function(target, where){ + where = where || (this.options.inject ? this.options.inject.where : '') || (this.target == document.body ? 'inside' : 'after'); + target = target || (this.options.inject && this.options.inject.target) || this.target; + + this.element.inject(target, where); + + if (this.options.useIframeShim){ + this.shim = new IframeShim(this.element, this.options.iframeShimOptions); + + this.addEvents({ + show: this.shim.show.bind(this.shim), + hide: this.shim.hide.bind(this.shim), + destroy: this.shim.destroy.bind(this.shim) + }); + } + }, + + position: function(){ + this.resize(this.options.width, this.options.height); + + this.element.position({ + relativeTo: this.target, + position: 'topLeft', + ignoreMargins: !this.options.maskMargins, + ignoreScroll: this.target == document.body + }); + + return this; + }, + + resize: function(x, y){ + var opt = { + styles: ['padding', 'border'] + }; + if (this.options.maskMargins) opt.styles.push('margin'); + + var dim = this.target.getComputedSize(opt); + if (this.target == document.body){ + this.element.setStyles({width: 0, height: 0}); + var win = window.getScrollSize(); + if (dim.totalHeight < win.y) dim.totalHeight = win.y; + if (dim.totalWidth < win.x) dim.totalWidth = win.x; + } + this.element.setStyles({ + width: Array.pick([x, dim.totalWidth, dim.x]), + height: Array.pick([y, dim.totalHeight, dim.y]) + }); + + return this; + }, + + show: function(){ + if (!this.hidden) return this; + + window.addEvent('resize', this.position); + this.position(); + this.showMask.apply(this, arguments); + + return this; + }, + + showMask: function(){ + this.element.setStyle('display', 'block'); + this.hidden = false; + this.fireEvent('show'); + }, + + hide: function(){ + if (this.hidden) return this; + + window.removeEvent('resize', this.position); + this.hideMask.apply(this, arguments); + if (this.options.destroyOnHide) return this.destroy(); + + return this; + }, + + hideMask: function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + }, + + toggle: function(){ + this[this.hidden ? 'show' : 'hide'](); + }, + + destroy: function(){ + this.hide(); + this.element.destroy(); + this.fireEvent('destroy'); + this.target.eliminate('mask'); + } + +}); + +Element.Properties.mask = { + + set: function(options){ + var mask = this.retrieve('mask'); + if (mask) mask.destroy(); + return this.eliminate('mask').store('mask:options', options); + }, + + get: function(){ + var mask = this.retrieve('mask'); + if (!mask){ + mask = new Mask(this, this.retrieve('mask:options')); + this.store('mask', mask); + } + return mask; + } + +}; + +Element.implement({ + + mask: function(options){ + if (options) this.set('mask', options); + this.get('mask').show(); + return this; + }, + + unmask: function(){ + this.get('mask').hide(); + return this; + } + +}); + + +/* +--- + +script: Spinner.js + +name: Spinner + +description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Tween + - Core/Request + - Class.refactor + - Mask + +provides: [Spinner] + +... +*/ + +var Spinner = new Class({ + + Extends: Mask, + + Implements: Chain, + + options: {/* + message: false,*/ + 'class': 'spinner', + containerPosition: {}, + content: { + 'class': 'spinner-content' + }, + messageContainer: { + 'class': 'spinner-msg' + }, + img: { + 'class': 'spinner-img' + }, + fxOptions: { + link: 'chain' + } + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('spinner', this); + this.setOptions(options); + this.render(); + this.inject(); + + // Add this to events for when noFx is true; parent methods handle hide/show. + var deactivate = function(){ this.active = false; }.bind(this); + this.addEvents({ + hide: deactivate, + show: deactivate + }); + }, + + render: function(){ + this.parent(); + + this.element.set('id', this.options.id || 'spinner-' + String.uniqueID()); + + this.content = document.id(this.options.content) || new Element('div', this.options.content); + this.content.inject(this.element); + + if (this.options.message){ + this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message); + this.msg.inject(this.content); + } + + if (this.options.img){ + this.img = document.id(this.options.img) || new Element('div', this.options.img); + this.img.inject(this.content); + } + + this.element.set('tween', this.options.fxOptions); + }, + + show: function(noFx){ + if (this.active) return this.chain(this.show.bind(this)); + if (!this.hidden){ + this.callChain.delay(20, this); + return this; + } + + this.target.set('aria-busy', 'true'); + this.active = true; + + return this.parent(noFx); + }, + + showMask: function(noFx){ + var pos = function(){ + this.content.position(Object.merge({ + relativeTo: this.element + }, this.options.containerPosition)); + }.bind(this); + + if (noFx){ + this.parent(); + pos(); + } else { + if (!this.options.style.opacity) this.options.style.opacity = this.element.getStyle('opacity').toFloat(); + this.element.setStyles({ + display: 'block', + opacity: 0 + }).tween('opacity', this.options.style.opacity); + pos(); + this.hidden = false; + this.fireEvent('show'); + this.callChain(); + } + }, + + hide: function(noFx){ + if (this.active) return this.chain(this.hide.bind(this)); + if (this.hidden){ + this.callChain.delay(20, this); + return this; + } + + this.target.set('aria-busy', 'false'); + this.active = true; + + return this.parent(noFx); + }, + + hideMask: function(noFx){ + if (noFx) return this.parent(); + this.element.tween('opacity', 0).get('tween').chain(function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + this.callChain(); + }.bind(this)); + }, + + destroy: function(){ + this.content.destroy(); + this.parent(); + this.target.eliminate('spinner'); + } + +}); + +Request = Class.refactor(Request, { + + options: { + useSpinner: false, + spinnerOptions: {}, + spinnerTarget: false + }, + + initialize: function(options){ + this._send = this.send; + this.send = function(options){ + var spinner = this.getSpinner(); + if (spinner) spinner.chain(this._send.pass(options, this)).show(); + else this._send(options); + return this; + }; + this.previous(options); + }, + + getSpinner: function(){ + if (!this.spinner){ + var update = document.id(this.options.spinnerTarget) || document.id(this.options.update); + if (this.options.useSpinner && update){ + update.set('spinner', this.options.spinnerOptions); + var spinner = this.spinner = update.get('spinner'); + ['complete', 'exception', 'cancel'].each(function(event){ + this.addEvent(event, spinner.hide.bind(spinner)); + }, this); + } + } + return this.spinner; + } + +}); + +Element.Properties.spinner = { + + set: function(options){ + var spinner = this.retrieve('spinner'); + if (spinner) spinner.destroy(); + return this.eliminate('spinner').store('spinner:options', options); + }, + + get: function(){ + var spinner = this.retrieve('spinner'); + if (!spinner){ + spinner = new Spinner(this, this.retrieve('spinner:options')); + this.store('spinner', spinner); + } + return spinner; + } + +}; + +Element.implement({ + + spin: function(options){ + if (options) this.set('spinner', options); + this.get('spinner').show(); + return this; + }, + + unspin: function(){ + this.get('spinner').hide(); + return this; + } + +}); + + +/* +--- + +script: String.QueryString.js + +name: String.QueryString + +description: Methods for dealing with URI query strings. + +license: MIT-style license + +authors: + - Sebastian Markbåge + - Aaron Newton + - Lennart Pilon + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - MooTools.More + +provides: [String.QueryString] + +... +*/ + +String.implement({ + + parseQueryString: function(decodeKeys, decodeValues){ + if (decodeKeys == null) decodeKeys = true; + if (decodeValues == null) decodeValues = true; + + var vars = this.split(/[&;]/), + object = {}; + if (!vars.length) return object; + + vars.each(function(val){ + var index = val.indexOf('=') + 1, + value = index ? val.substr(index) : '', + keys = index ? val.substr(0, index - 1).match(/([^\]\[]+|(\B)(?=\]))/g) : [val], + obj = object; + if (!keys) return; + if (decodeValues) value = decodeURIComponent(value); + keys.each(function(key, i){ + if (decodeKeys) key = decodeURIComponent(key); + var current = obj[key]; + + if (i < keys.length - 1) obj = obj[key] = current || {}; + else if (typeOf(current) == 'array') current.push(value); + else obj[key] = current != null ? [current, value] : value; + }); + }); + + return object; + }, + + cleanQueryString: function(method){ + return this.split('&').filter(function(val){ + var index = val.indexOf('='), + key = index < 0 ? '' : val.substr(0, index), + value = val.substr(index + 1); + + return method ? method.call(null, key, value) : (value || value === 0); + }).join('&'); + } + +}); + + +/* +--- + +name: Events.Pseudos + +description: Adds the functionality to add pseudo events + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Class.Extras, Core/Slick.Parser, MooTools.More] + +provides: [Events.Pseudos] + +... +*/ + +(function(){ + +Events.Pseudos = function(pseudos, addEvent, removeEvent){ + + var storeKey = '_monitorEvents:'; + + var storageOf = function(object){ + return { + store: object.store ? function(key, value){ + object.store(storeKey + key, value); + } : function(key, value){ + (object._monitorEvents || (object._monitorEvents = {}))[key] = value; + }, + retrieve: object.retrieve ? function(key, dflt){ + return object.retrieve(storeKey + key, dflt); + } : function(key, dflt){ + if (!object._monitorEvents) return dflt; + return object._monitorEvents[key] || dflt; + } + }; + }; + + var splitType = function(type){ + if (type.indexOf(':') == -1 || !pseudos) return null; + + var parsed = Slick.parse(type).expressions[0][0], + parsedPseudos = parsed.pseudos, + l = parsedPseudos.length, + splits = []; + + while (l--){ + var pseudo = parsedPseudos[l].key, + listener = pseudos[pseudo]; + if (listener != null) splits.push({ + event: parsed.tag, + value: parsedPseudos[l].value, + pseudo: pseudo, + original: type, + listener: listener + }); + } + return splits.length ? splits : null; + }; + + return { + + addEvent: function(type, fn, internal){ + var split = splitType(type); + if (!split) return addEvent.call(this, type, fn, internal); + + var storage = storageOf(this), + events = storage.retrieve(type, []), + eventType = split[0].event, + args = Array.slice(arguments, 2), + stack = fn, + self = this; + + split.each(function(item){ + var listener = item.listener, + stackFn = stack; + if (listener == false) eventType += ':' + item.pseudo + '(' + item.value + ')'; + else stack = function(){ + listener.call(self, item, stackFn, arguments, stack); + }; + }); + + events.include({type: eventType, event: fn, monitor: stack}); + storage.store(type, events); + + if (type != eventType) addEvent.apply(this, [type, fn].concat(args)); + return addEvent.apply(this, [eventType, stack].concat(args)); + }, + + removeEvent: function(type, fn){ + var split = splitType(type); + if (!split) return removeEvent.call(this, type, fn); + + var storage = storageOf(this), + events = storage.retrieve(type); + if (!events) return this; + + var args = Array.slice(arguments, 2); + + removeEvent.apply(this, [type, fn].concat(args)); + events.each(function(monitor, i){ + if (!fn || monitor.event == fn) removeEvent.apply(this, [monitor.type, monitor.monitor].concat(args)); + delete events[i]; + }, this); + + storage.store(type, events); + return this; + } + + }; + +}; + +var pseudos = { + + once: function(split, fn, args, monitor){ + fn.apply(this, args); + this.removeEvent(split.event, monitor) + .removeEvent(split.original, fn); + }, + + throttle: function(split, fn, args){ + if (!fn._throttled){ + fn.apply(this, args); + fn._throttled = setTimeout(function(){ + fn._throttled = false; + }, split.value || 250); + } + }, + + pause: function(split, fn, args){ + clearTimeout(fn._pause); + fn._pause = fn.delay(split.value || 250, this, args); + } + +}; + +Events.definePseudo = function(key, listener){ + pseudos[key] = listener; + return this; +}; + +Events.lookupPseudo = function(key){ + return pseudos[key]; +}; + +var proto = Events.prototype; +Events.implement(Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +['Request', 'Fx'].each(function(klass){ + if (this[klass]) this[klass].implement(Events.prototype); +}); + +})(); + + +/* +--- + +name: Element.Event.Pseudos + +description: Adds the functionality to add pseudo events for Elements + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Element.Event, Core/Element.Delegation, Events.Pseudos] + +provides: [Element.Event.Pseudos, Element.Delegation.Pseudo] + +... +*/ + +(function(){ + +var pseudos = {relay: false}, + copyFromEvents = ['once', 'throttle', 'pause'], + count = copyFromEvents.length; + +while (count--) pseudos[copyFromEvents[count]] = Events.lookupPseudo(copyFromEvents[count]); + +DOMEvent.definePseudo = function(key, listener){ + pseudos[key] = listener; + return this; +}; + +var proto = Element.prototype; +[Element, Window, Document].invoke('implement', Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +})(); + + +/* +--- + +script: Form.Request.js + +name: Form.Request + +description: Handles the basic functionality of submitting a form and updating a dom element with the result. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Request.HTML + - Class.Binds + - Class.Occlude + - Spinner + - String.QueryString + - Element.Delegation.Pseudo + +provides: [Form.Request] + +... +*/ + +if (!window.Form) window.Form = {}; + +(function(){ + + Form.Request = new Class({ + + Binds: ['onSubmit', 'onFormValidate'], + + Implements: [Options, Events, Class.Occlude], + + options: {/* + onFailure: function(){}, + onSuccess: function(){}, // aliased to onComplete, + onSend: function(){}*/ + requestOptions: { + evalScripts: true, + useSpinner: true, + emulation: false, + link: 'ignore' + }, + sendButtonClicked: true, + extraData: {}, + resetForm: true + }, + + property: 'form.request', + + initialize: function(form, target, options){ + this.element = document.id(form); + if (this.occlude()) return this.occluded; + this.setOptions(options) + .setTarget(target) + .attach(); + }, + + setTarget: function(target){ + this.target = document.id(target); + if (!this.request){ + this.makeRequest(); + } else { + this.request.setOptions({ + update: this.target + }); + } + return this; + }, + + toElement: function(){ + return this.element; + }, + + makeRequest: function(){ + var self = this; + this.request = new Request.HTML(Object.merge({ + update: this.target, + emulation: false, + spinnerTarget: this.element, + method: this.element.get('method') || 'post' + }, this.options.requestOptions)).addEvents({ + success: function(tree, elements, html, javascript){ + ['complete', 'success'].each(function(evt){ + self.fireEvent(evt, [self.target, tree, elements, html, javascript]); + }); + }, + failure: function(){ + self.fireEvent('complete', arguments).fireEvent('failure', arguments); + }, + exception: function(){ + self.fireEvent('failure', arguments); + } + }); + return this.attachReset(); + }, + + attachReset: function(){ + if (!this.options.resetForm) return this; + this.request.addEvent('success', function(){ + Function.attempt(function(){ + this.element.reset(); + }.bind(this)); + if (window.OverText) OverText.update(); + }.bind(this)); + return this; + }, + + attach: function(attach){ + var method = (attach != false) ? 'addEvent' : 'removeEvent'; + this.element[method]('click:relay(button, input[type=submit])', this.saveClickedButton.bind(this)); + + var fv = this.element.retrieve('validator'); + if (fv) fv[method]('onFormValidate', this.onFormValidate); + else this.element[method]('submit', this.onSubmit); + + return this; + }, + + detach: function(){ + return this.attach(false); + }, + + //public method + enable: function(){ + return this.attach(); + }, + + //public method + disable: function(){ + return this.detach(); + }, + + onFormValidate: function(valid, form, event){ + //if there's no event, then this wasn't a submit event + if (!event) return; + var fv = this.element.retrieve('validator'); + if (valid || (fv && !fv.options.stopOnFailure)){ + event.stop(); + this.send(); + } + }, + + onSubmit: function(event){ + var fv = this.element.retrieve('validator'); + if (fv){ + //form validator was created after Form.Request + this.element.removeEvent('submit', this.onSubmit); + fv.addEvent('onFormValidate', this.onFormValidate); + fv.validate(event); + return; + } + if (event) event.stop(); + this.send(); + }, + + saveClickedButton: function(event, target){ + var targetName = target.get('name'); + if (!targetName || !this.options.sendButtonClicked) return; + this.options.extraData[targetName] = target.get('value') || true; + this.clickedCleaner = function(){ + delete this.options.extraData[targetName]; + this.clickedCleaner = function(){}; + }.bind(this); + }, + + clickedCleaner: function(){}, + + send: function(){ + var str = this.element.toQueryString().trim(), + data = Object.toQueryString(this.options.extraData); + + if (str) str += "&" + data; + else str = data; + + this.fireEvent('send', [this.element, str.parseQueryString()]); + this.request.send({ + data: str, + url: this.options.requestOptions.url || this.element.get('action') + }); + this.clickedCleaner(); + return this; + } + + }); + + Element.implement('formUpdate', function(update, options){ + var fq = this.retrieve('form.request'); + if (!fq){ + fq = new Form.Request(this, update, options); + } else { + if (update) fq.setTarget(update); + if (options) fq.setOptions(options).makeRequest(); + } + fq.send(); + return this; + }); + +})(); + + +/* +--- + +script: Element.Shortcuts.js + +name: Element.Shortcuts + +description: Extends the Element native object to include some shortcut methods. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - MooTools.More + +provides: [Element.Shortcuts] + +... +*/ + +Element.implement({ + + isDisplayed: function(){ + return this.getStyle('display') != 'none'; + }, + + isVisible: function(){ + var w = this.offsetWidth, + h = this.offsetHeight; + return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.style.display != 'none'; + }, + + toggle: function(){ + return this[this.isDisplayed() ? 'hide' : 'show'](); + }, + + hide: function(){ + var d; + try { + //IE fails here if the element is not in the dom + d = this.getStyle('display'); + } catch(e){} + if (d == 'none') return this; + return this.store('element:_originalDisplay', d || '').setStyle('display', 'none'); + }, + + show: function(display){ + if (!display && this.isDisplayed()) return this; + display = display || this.retrieve('element:_originalDisplay') || 'block'; + return this.setStyle('display', (display == 'none') ? 'block' : display); + }, + + swapClass: function(remove, add){ + return this.removeClass(remove).addClass(add); + } + +}); + +Document.implement({ + + clearSelection: function(){ + if (window.getSelection){ + var selection = window.getSelection(); + if (selection && selection.removeAllRanges) selection.removeAllRanges(); + } else if (document.selection && document.selection.empty){ + try { + //IE fails here if selected element is not in dom + document.selection.empty(); + } catch(e){} + } + } + +}); + + +/* +--- + +script: Fx.Reveal.js + +name: Fx.Reveal + +description: Defines Fx.Reveal, a class that shows and hides elements with a transition. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Morph + - Element.Shortcuts + - Element.Measure + +provides: [Fx.Reveal] + +... +*/ + +(function(){ + + +var hideTheseOf = function(object){ + var hideThese = object.options.hideInputs; + if (window.OverText){ + var otClasses = [null]; + OverText.each(function(ot){ + otClasses.include('.' + ot.options.labelClass); + }); + if (otClasses) hideThese += otClasses.join(', '); + } + return (hideThese) ? object.element.getElements(hideThese) : null; +}; + + +Fx.Reveal = new Class({ + + Extends: Fx.Morph, + + options: {/* + onShow: function(thisElement){}, + onHide: function(thisElement){}, + onComplete: function(thisElement){}, + heightOverride: null, + widthOverride: null,*/ + link: 'cancel', + styles: ['padding', 'border', 'margin'], + transitionOpacity: 'opacity' in document.documentElement, + mode: 'vertical', + display: function(){ + return this.element.get('tag') != 'tr' ? 'block' : 'table-row'; + }, + opacity: 1, + hideInputs: !('opacity' in document.documentElement) ? 'select, input, textarea, object, embed' : null + }, + + dissolve: function(){ + if (!this.hiding && !this.showing){ + if (this.element.getStyle('display') != 'none'){ + this.hiding = true; + this.showing = false; + this.hidden = true; + this.cssText = this.element.style.cssText; + + var startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + if (this.options.transitionOpacity) startStyles.opacity = this.options.opacity; + + var zero = {}; + Object.each(startStyles, function(style, name){ + zero[name] = [style, 0]; + }); + + this.element.setStyles({ + display: Function.from(this.options.display).call(this), + overflow: 'hidden' + }); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + if (this.hidden){ + this.hiding = false; + this.element.style.cssText = this.cssText; + this.element.setStyle('display', 'none'); + if (hideThese) hideThese.setStyle('visibility', 'visible'); + } + this.fireEvent('hide', this.element); + this.callChain(); + }.bind(this)); + + this.start(zero); + } else { + this.callChain.delay(10, this); + this.fireEvent('complete', this.element); + this.fireEvent('hide', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.dissolve.bind(this)); + } else if (this.options.link == 'cancel' && !this.hiding){ + this.cancel(); + this.dissolve(); + } + return this; + }, + + reveal: function(){ + if (!this.showing && !this.hiding){ + if (this.element.getStyle('display') == 'none'){ + this.hiding = false; + this.showing = true; + this.hidden = false; + this.cssText = this.element.style.cssText; + + var startStyles; + this.element.measure(function(){ + startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + }.bind(this)); + if (this.options.heightOverride != null) startStyles.height = this.options.heightOverride.toInt(); + if (this.options.widthOverride != null) startStyles.width = this.options.widthOverride.toInt(); + if (this.options.transitionOpacity){ + this.element.setStyle('opacity', 0); + startStyles.opacity = this.options.opacity; + } + + var zero = { + height: 0, + display: Function.from(this.options.display).call(this) + }; + Object.each(startStyles, function(style, name){ + zero[name] = 0; + }); + zero.overflow = 'hidden'; + + this.element.setStyles(zero); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + this.element.style.cssText = this.cssText; + this.element.setStyle('display', Function.from(this.options.display).call(this)); + if (!this.hidden) this.showing = false; + if (hideThese) hideThese.setStyle('visibility', 'visible'); + this.callChain(); + this.fireEvent('show', this.element); + }.bind(this)); + + this.start(startStyles); + } else { + this.callChain(); + this.fireEvent('complete', this.element); + this.fireEvent('show', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.reveal.bind(this)); + } else if (this.options.link == 'cancel' && !this.showing){ + this.cancel(); + this.reveal(); + } + return this; + }, + + toggle: function(){ + if (this.element.getStyle('display') == 'none'){ + this.reveal(); + } else { + this.dissolve(); + } + return this; + }, + + cancel: function(){ + this.parent.apply(this, arguments); + if (this.cssText != null) this.element.style.cssText = this.cssText; + this.hiding = false; + this.showing = false; + return this; + } + +}); + +Element.Properties.reveal = { + + set: function(options){ + this.get('reveal').cancel().setOptions(options); + return this; + }, + + get: function(){ + var reveal = this.retrieve('reveal'); + if (!reveal){ + reveal = new Fx.Reveal(this); + this.store('reveal', reveal); + } + return reveal; + } + +}; + +Element.Properties.dissolve = Element.Properties.reveal; + +Element.implement({ + + reveal: function(options){ + this.get('reveal').setOptions(options).reveal(); + return this; + }, + + dissolve: function(options){ + this.get('reveal').setOptions(options).dissolve(); + return this; + }, + + nix: function(options){ + var params = Array.link(arguments, {destroy: Type.isBoolean, options: Type.isObject}); + this.get('reveal').setOptions(options).dissolve().chain(function(){ + this[params.destroy ? 'destroy' : 'dispose'](); + }.bind(this)); + return this; + }, + + wink: function(){ + var params = Array.link(arguments, {duration: Type.isNumber, options: Type.isObject}); + var reveal = this.get('reveal').setOptions(params.options); + reveal.reveal().chain(function(){ + (function(){ + reveal.dissolve(); + }).delay(params.duration || 2000); + }); + } + +}); + +})(); + + +/* +--- + +script: Drag.js + +name: Drag + +description: The base Drag Class. Can be used to drag and resize Elements using mouse events. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + +requires: + - Core/Events + - Core/Options + - Core/Element.Event + - Core/Element.Style + - Core/Element.Dimensions + - MooTools.More + +provides: [Drag] +... + +*/ + +var Drag = new Class({ + + Implements: [Events, Options], + + options: {/* + onBeforeStart: function(thisElement){}, + onStart: function(thisElement, event){}, + onSnap: function(thisElement){}, + onDrag: function(thisElement, event){}, + onCancel: function(thisElement){}, + onComplete: function(thisElement, event){},*/ + snap: 6, + unit: 'px', + grid: false, + style: true, + limit: false, + handle: false, + invert: false, + preventDefault: false, + stopPropagation: false, + modifiers: {x: 'left', y: 'top'} + }, + + initialize: function(){ + var params = Array.link(arguments, { + 'options': Type.isObject, + 'element': function(obj){ + return obj != null; + } + }); + + this.element = document.id(params.element); + this.document = this.element.getDocument(); + this.setOptions(params.options || {}); + var htype = typeOf(this.options.handle); + this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element; + this.mouse = {'now': {}, 'pos': {}}; + this.value = {'start': {}, 'now': {}}; + + this.selection = 'selectstart' in document ? 'selectstart' : 'mousedown'; + + + if ('ondragstart' in document && !('FileReader' in window) && !Drag.ondragstartFixed){ + document.ondragstart = Function.from(false); + Drag.ondragstartFixed = true; + } + + this.bound = { + start: this.start.bind(this), + check: this.check.bind(this), + drag: this.drag.bind(this), + stop: this.stop.bind(this), + cancel: this.cancel.bind(this), + eventStop: Function.from(false) + }; + this.attach(); + }, + + attach: function(){ + this.handles.addEvent('mousedown', this.bound.start); + return this; + }, + + detach: function(){ + this.handles.removeEvent('mousedown', this.bound.start); + return this; + }, + + start: function(event){ + var options = this.options; + + if (event.rightClick) return; + + if (options.preventDefault) event.preventDefault(); + if (options.stopPropagation) event.stopPropagation(); + this.mouse.start = event.page; + + this.fireEvent('beforeStart', this.element); + + var limit = options.limit; + this.limit = {x: [], y: []}; + + var z, coordinates; + for (z in options.modifiers){ + if (!options.modifiers[z]) continue; + + var style = this.element.getStyle(options.modifiers[z]); + + // Some browsers (IE and Opera) don't always return pixels. + if (style && !style.match(/px$/)){ + if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent()); + style = coordinates[options.modifiers[z]]; + } + + if (options.style) this.value.now[z] = (style || 0).toInt(); + else this.value.now[z] = this.element[options.modifiers[z]]; + + if (options.invert) this.value.now[z] *= -1; + + this.mouse.pos[z] = event.page[z] - this.value.now[z]; + + if (limit && limit[z]){ + var i = 2; + while (i--){ + var limitZI = limit[z][i]; + if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI; + } + } + } + + if (typeOf(this.options.grid) == 'number') this.options.grid = { + x: this.options.grid, + y: this.options.grid + }; + + var events = { + mousemove: this.bound.check, + mouseup: this.bound.cancel + }; + events[this.selection] = this.bound.eventStop; + this.document.addEvents(events); + }, + + check: function(event){ + if (this.options.preventDefault) event.preventDefault(); + var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2))); + if (distance > this.options.snap){ + this.cancel(); + this.document.addEvents({ + mousemove: this.bound.drag, + mouseup: this.bound.stop + }); + this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element); + } + }, + + drag: function(event){ + var options = this.options; + + if (options.preventDefault) event.preventDefault(); + this.mouse.now = event.page; + + for (var z in options.modifiers){ + if (!options.modifiers[z]) continue; + this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; + + if (options.invert) this.value.now[z] *= -1; + + if (options.limit && this.limit[z]){ + if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){ + this.value.now[z] = this.limit[z][1]; + } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){ + this.value.now[z] = this.limit[z][0]; + } + } + + if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]); + + if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit); + else this.element[options.modifiers[z]] = this.value.now[z]; + } + + this.fireEvent('drag', [this.element, event]); + }, + + cancel: function(event){ + this.document.removeEvents({ + mousemove: this.bound.check, + mouseup: this.bound.cancel + }); + if (event){ + this.document.removeEvent(this.selection, this.bound.eventStop); + this.fireEvent('cancel', this.element); + } + }, + + stop: function(event){ + var events = { + mousemove: this.bound.drag, + mouseup: this.bound.stop + }; + events[this.selection] = this.bound.eventStop; + this.document.removeEvents(events); + if (event) this.fireEvent('complete', [this.element, event]); + } + +}); + +Element.implement({ + + makeResizable: function(options){ + var drag = new Drag(this, Object.merge({ + modifiers: { + x: 'width', + y: 'height' + } + }, options)); + + this.store('resizer', drag); + return drag.addEvent('drag', function(){ + this.fireEvent('resize', drag); + }.bind(this)); + } + +}); + + +/* +--- + +script: Drag.Move.js + +name: Drag.Move + +description: A Drag extension that provides support for the constraining of draggables to containers and droppables. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + - Aaron Newton + - Scott Kyle + +requires: + - Core/Element.Dimensions + - Drag + +provides: [Drag.Move] + +... +*/ + +Drag.Move = new Class({ + + Extends: Drag, + + options: {/* + onEnter: function(thisElement, overed){}, + onLeave: function(thisElement, overed){}, + onDrop: function(thisElement, overed, event){},*/ + droppables: [], + container: false, + precalculate: false, + includeMargins: true, + checkDroppables: true + }, + + initialize: function(element, options){ + this.parent(element, options); + element = this.element; + + this.droppables = $$(this.options.droppables); + this.setContainer(this.options.container); + + if (this.options.style){ + if (this.options.modifiers.x == 'left' && this.options.modifiers.y == 'top'){ + var parent = element.getOffsetParent(), + styles = element.getStyles('left', 'top'); + if (parent && (styles.left == 'auto' || styles.top == 'auto')){ + element.setPosition(element.getPosition(parent)); + } + } + + if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute'); + } + + this.addEvent('start', this.checkDroppables, true); + this.overed = null; + }, + + setContainer: function(container) { + this.container = document.id(container); + if (this.container && typeOf(this.container) != 'element'){ + this.container = document.id(this.container.getDocument().body); + } + }, + + start: function(event){ + if (this.container) this.options.limit = this.calculateLimit(); + + if (this.options.precalculate){ + this.positions = this.droppables.map(function(el){ + return el.getCoordinates(); + }); + } + + this.parent(event); + }, + + calculateLimit: function(){ + var element = this.element, + container = this.container, + + offsetParent = document.id(element.getOffsetParent()) || document.body, + containerCoordinates = container.getCoordinates(offsetParent), + elementMargin = {}, + elementBorder = {}, + containerMargin = {}, + containerBorder = {}, + offsetParentPadding = {}; + + ['top', 'right', 'bottom', 'left'].each(function(pad){ + elementMargin[pad] = element.getStyle('margin-' + pad).toInt(); + elementBorder[pad] = element.getStyle('border-' + pad).toInt(); + containerMargin[pad] = container.getStyle('margin-' + pad).toInt(); + containerBorder[pad] = container.getStyle('border-' + pad).toInt(); + offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt(); + }, this); + + var width = element.offsetWidth + elementMargin.left + elementMargin.right, + height = element.offsetHeight + elementMargin.top + elementMargin.bottom, + left = 0, + top = 0, + right = containerCoordinates.right - containerBorder.right - width, + bottom = containerCoordinates.bottom - containerBorder.bottom - height; + + if (this.options.includeMargins){ + left += elementMargin.left; + top += elementMargin.top; + } else { + right += elementMargin.right; + bottom += elementMargin.bottom; + } + + if (element.getStyle('position') == 'relative'){ + var coords = element.getCoordinates(offsetParent); + coords.left -= element.getStyle('left').toInt(); + coords.top -= element.getStyle('top').toInt(); + + left -= coords.left; + top -= coords.top; + if (container.getStyle('position') != 'relative'){ + left += containerBorder.left; + top += containerBorder.top; + } + right += elementMargin.left - coords.left; + bottom += elementMargin.top - coords.top; + + if (container != offsetParent){ + left += containerMargin.left + offsetParentPadding.left; + if (!offsetParentPadding.left && left < 0) left = 0; + top += offsetParent == document.body ? 0 : containerMargin.top + offsetParentPadding.top; + if (!offsetParentPadding.top && top < 0) top = 0; + } + } else { + left -= elementMargin.left; + top -= elementMargin.top; + if (container != offsetParent){ + left += containerCoordinates.left + containerBorder.left; + top += containerCoordinates.top + containerBorder.top; + } + } + + return { + x: [left, right], + y: [top, bottom] + }; + }, + + getDroppableCoordinates: function(element){ + var position = element.getCoordinates(); + if (element.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.left += scroll.x; + position.right += scroll.x; + position.top += scroll.y; + position.bottom += scroll.y; + } + return position; + }, + + checkDroppables: function(){ + var overed = this.droppables.filter(function(el, i){ + el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el); + var now = this.mouse.now; + return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top); + }, this).getLast(); + + if (this.overed != overed){ + if (this.overed) this.fireEvent('leave', [this.element, this.overed]); + if (overed) this.fireEvent('enter', [this.element, overed]); + this.overed = overed; + } + }, + + drag: function(event){ + this.parent(event); + if (this.options.checkDroppables && this.droppables.length) this.checkDroppables(); + }, + + stop: function(event){ + this.checkDroppables(); + this.fireEvent('drop', [this.element, this.overed, event]); + this.overed = null; + return this.parent(event); + } + +}); + +Element.implement({ + + makeDraggable: function(options){ + var drag = new Drag.Move(this, options); + this.store('dragger', drag); + return drag; + } + +}); + + +/* +--- + +script: Sortables.js + +name: Sortables + +description: Class for creating a drag and drop sorting interface for lists of items. + +license: MIT-style license + +authors: + - Tom Occhino + +requires: + - Core/Fx.Morph + - Drag.Move + +provides: [Sortables] + +... +*/ + +var Sortables = new Class({ + + Implements: [Events, Options], + + options: {/* + onSort: function(element, clone){}, + onStart: function(element, clone){}, + onComplete: function(element){},*/ + opacity: 1, + clone: false, + revert: false, + handle: false, + dragOptions: {}, + unDraggableTags: ['button', 'input', 'a', 'textarea', 'select', 'option'] + }, + + initialize: function(lists, options){ + this.setOptions(options); + + this.elements = []; + this.lists = []; + this.idle = true; + + this.addLists($$(document.id(lists) || lists)); + + if (!this.options.clone) this.options.revert = false; + if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({ + duration: 250, + link: 'cancel' + }, this.options.revert)); + }, + + attach: function(){ + this.addLists(this.lists); + return this; + }, + + detach: function(){ + this.lists = this.removeLists(this.lists); + return this; + }, + + addItems: function(){ + Array.flatten(arguments).each(function(element){ + this.elements.push(element); + var start = element.retrieve('sortables:start', function(event){ + this.start.call(this, event, element); + }.bind(this)); + (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start); + }, this); + return this; + }, + + addLists: function(){ + Array.flatten(arguments).each(function(list){ + this.lists.include(list); + this.addItems(list.getChildren()); + }, this); + return this; + }, + + removeItems: function(){ + return $$(Array.flatten(arguments).map(function(element){ + this.elements.erase(element); + var start = element.retrieve('sortables:start'); + (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start); + + return element; + }, this)); + }, + + removeLists: function(){ + return $$(Array.flatten(arguments).map(function(list){ + this.lists.erase(list); + this.removeItems(list.getChildren()); + + return list; + }, this)); + }, + + getDroppableCoordinates: function (element){ + var offsetParent = element.getOffsetParent(); + var position = element.getPosition(offsetParent); + var scroll = { + w: window.getScroll(), + offsetParent: offsetParent.getScroll() + }; + position.x += scroll.offsetParent.x; + position.y += scroll.offsetParent.y; + + if (offsetParent.getStyle('position') == 'fixed'){ + position.x -= scroll.w.x; + position.y -= scroll.w.y; + } + + return position; + }, + + getClone: function(event, element){ + if (!this.options.clone) return new Element(element.tagName).inject(document.body); + if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list); + var clone = element.clone(true).setStyles({ + margin: 0, + position: 'absolute', + visibility: 'hidden', + width: element.getStyle('width') + }).addEvent('mousedown', function(event){ + element.fireEvent('mousedown', event); + }); + //prevent the duplicated radio inputs from unchecking the real one + if (clone.get('html').test('radio')){ + clone.getElements('input[type=radio]').each(function(input, i){ + input.set('name', 'clone_' + i); + if (input.get('checked')) element.getElements('input[type=radio]')[i].set('checked', true); + }); + } + + return clone.inject(this.list).setPosition(this.getDroppableCoordinates(this.element)); + }, + + getDroppables: function(){ + var droppables = this.list.getChildren().erase(this.clone).erase(this.element); + if (!this.options.constrain) droppables.append(this.lists).erase(this.list); + return droppables; + }, + + insert: function(dragging, element){ + var where = 'inside'; + if (this.lists.contains(element)){ + this.list = element; + this.drag.droppables = this.getDroppables(); + } else { + where = this.element.getAllPrevious().contains(element) ? 'before' : 'after'; + } + this.element.inject(element, where); + this.fireEvent('sort', [this.element, this.clone]); + }, + + start: function(event, element){ + if ( + !this.idle || + event.rightClick || + (!this.options.handle && this.options.unDraggableTags.contains(event.target.get('tag'))) + ) return; + + this.idle = false; + this.element = element; + this.opacity = element.getStyle('opacity'); + this.list = element.getParent(); + this.clone = this.getClone(event, element); + + this.drag = new Drag.Move(this.clone, Object.merge({ + + droppables: this.getDroppables() + }, this.options.dragOptions)).addEvents({ + onSnap: function(){ + event.stop(); + this.clone.setStyle('visibility', 'visible'); + this.element.setStyle('opacity', this.options.opacity || 0); + this.fireEvent('start', [this.element, this.clone]); + }.bind(this), + onEnter: this.insert.bind(this), + onCancel: this.end.bind(this), + onComplete: this.end.bind(this) + }); + + this.clone.inject(this.element, 'before'); + this.drag.start(event); + }, + + end: function(){ + this.drag.detach(); + this.element.setStyle('opacity', this.opacity); + var self = this; + if (this.effect){ + var dim = this.element.getStyles('width', 'height'), + clone = this.clone, + pos = clone.computePosition(this.getDroppableCoordinates(clone)); + + var destroy = function(){ + this.removeEvent('cancel', destroy); + clone.destroy(); + self.reset(); + }; + + this.effect.element = clone; + this.effect.start({ + top: pos.top, + left: pos.left, + width: dim.width, + height: dim.height, + opacity: 0.25 + }).addEvent('cancel', destroy).chain(destroy); + } else { + this.clone.destroy(); + self.reset(); + } + + }, + + reset: function(){ + this.idle = true; + this.fireEvent('complete', this.element); + }, + + serialize: function(){ + var params = Array.link(arguments, { + modifier: Type.isFunction, + index: function(obj){ + return obj != null; + } + }); + var serial = this.lists.map(function(list){ + return list.getChildren().map(params.modifier || function(element){ + return element.get('id'); + }, this); + }, this); + + var index = params.index; + if (this.lists.length == 1) index = 0; + return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial; + } + +}); + + +/* +--- + +script: Request.Periodical.js + +name: Request.Periodical + +description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load + +license: MIT-style license + +authors: + - Christoph Pojer + +requires: + - Core/Request + - MooTools.More + +provides: [Request.Periodical] + +... +*/ + +Request.implement({ + + options: { + initialDelay: 5000, + delay: 5000, + limit: 60000 + }, + + startTimer: function(data){ + var fn = function(){ + if (!this.running) this.send({data: data}); + }; + this.lastDelay = this.options.initialDelay; + this.timer = fn.delay(this.lastDelay, this); + this.completeCheck = function(response){ + clearTimeout(this.timer); + this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit); + this.timer = fn.delay(this.lastDelay, this); + }; + return this.addEvent('complete', this.completeCheck); + }, + + stopTimer: function(){ + clearTimeout(this.timer); + return this.removeEvent('complete', this.completeCheck); + } + +}); + + +/* +--- + +script: Color.js + +name: Color + +description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - Core/Number + - Core/Hash + - Core/Function + - MooTools.More + +provides: [Color] + +... +*/ + +(function(){ + +var Color = this.Color = new Type('Color', function(color, type){ + if (arguments.length >= 3){ + type = 'rgb'; color = Array.slice(arguments, 0, 3); + } else if (typeof color == 'string'){ + if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true); + else if (color.match(/hsb/)) color = color.hsbToRgb(); + else color = color.hexToRgb(true); + } + type = type || 'rgb'; + switch (type){ + case 'hsb': + var old = color; + color = color.hsbToRgb(); + color.hsb = old; + break; + case 'hex': color = color.hexToRgb(true); break; + } + color.rgb = color.slice(0, 3); + color.hsb = color.hsb || color.rgbToHsb(); + color.hex = color.rgbToHex(); + return Object.append(color, this); +}); + +Color.implement({ + + mix: function(){ + var colors = Array.slice(arguments); + var alpha = (typeOf(colors.getLast()) == 'number') ? colors.pop() : 50; + var rgb = this.slice(); + colors.each(function(color){ + color = new Color(color); + for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha)); + }); + return new Color(rgb, 'rgb'); + }, + + invert: function(){ + return new Color(this.map(function(value){ + return 255 - value; + })); + }, + + setHue: function(value){ + return new Color([value, this.hsb[1], this.hsb[2]], 'hsb'); + }, + + setSaturation: function(percent){ + return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb'); + }, + + setBrightness: function(percent){ + return new Color([this.hsb[0], this.hsb[1], percent], 'hsb'); + } + +}); + +this.$RGB = function(r, g, b){ + return new Color([r, g, b], 'rgb'); +}; + +this.$HSB = function(h, s, b){ + return new Color([h, s, b], 'hsb'); +}; + +this.$HEX = function(hex){ + return new Color(hex, 'hex'); +}; + +Array.implement({ + + rgbToHsb: function(){ + var red = this[0], + green = this[1], + blue = this[2], + hue = 0; + var max = Math.max(red, green, blue), + min = Math.min(red, green, blue); + var delta = max - min; + var brightness = max / 255, + saturation = (max != 0) ? delta / max : 0; + if (saturation != 0){ + var rr = (max - red) / delta; + var gr = (max - green) / delta; + var br = (max - blue) / delta; + if (red == max) hue = br - gr; + else if (green == max) hue = 2 + rr - br; + else hue = 4 + gr - rr; + hue /= 6; + if (hue < 0) hue++; + } + return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)]; + }, + + hsbToRgb: function(){ + var br = Math.round(this[2] / 100 * 255); + if (this[1] == 0){ + return [br, br, br]; + } else { + var hue = this[0] % 360; + var f = hue % 60; + var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255); + var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255); + var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255); + switch (Math.floor(hue / 60)){ + case 0: return [br, t, p]; + case 1: return [q, br, p]; + case 2: return [p, br, t]; + case 3: return [p, q, br]; + case 4: return [t, p, br]; + case 5: return [br, p, q]; + } + } + return false; + } + +}); + +String.implement({ + + rgbToHsb: function(){ + var rgb = this.match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHsb() : null; + }, + + hsbToRgb: function(){ + var hsb = this.match(/\d{1,3}/g); + return (hsb) ? hsb.hsbToRgb() : null; + } + +}); + +})(); + + diff --git a/module/webui/themes/flat/js/static/mootools-more.min.js b/module/webui/themes/flat/js/static/mootools-more.min.js new file mode 100644 index 000000000..ce03a60fd --- /dev/null +++ b/module/webui/themes/flat/js/static/mootools-more.min.js @@ -0,0 +1,226 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/more/c1cc18c2fff04bcc58921b4dff80a6f1 + +packager build: + - packager build More/Form.Request More/Fx.Reveal More/Sortables More/Request.Periodical More/Color + +copyrights: + - [MooTools](http://mootools.net) + +licenses: + - [MIT License](http://mootools.net/license.txt) +... +*/ + +MooTools.More={version:"1.5.0",build:"73db5e24e6e9c5c87b3a27aebef2248053f7db37"};Class.Mutators.Binds=function(a){if(!this.prototype.initialize){this.implement("initialize",function(){}); +}return Array.from(a).concat(this.prototype.Binds||[]);};Class.Mutators.initialize=function(a){return function(){Array.from(this.Binds).each(function(b){var c=this[b]; +if(c){this[b]=c.bind(this);}},this);return a.apply(this,arguments);};};Class.Occlude=new Class({occlude:function(c,b){b=document.id(b||this.element);var a=b.retrieve(c||this.property); +if(a&&!this.occluded){return(this.occluded=a);}this.occluded=false;b.store(c||this.property,this);return this.occluded;}});Class.refactor=function(b,a){Object.each(a,function(e,d){var c=b.prototype[d]; +c=(c&&c.$origin)||c||function(){};b.implement(d,(typeof e=="function")?function(){var f=this.previous;this.previous=c;var g=e.apply(this,arguments);this.previous=f; +return g;}:e);});return b;};(function(){var b=function(e,d){var f=[];Object.each(d,function(g){Object.each(g,function(h){e.each(function(i){f.push(i+"-"+h+(i=="border"?"-width":"")); +});});});return f;};var c=function(f,e){var d=0;Object.each(e,function(h,g){if(g.test(f)){d=d+h.toInt();}});return d;};var a=function(d){return !!(!d||d.offsetHeight||d.offsetWidth); +};Element.implement({measure:function(h){if(a(this)){return h.call(this);}var g=this.getParent(),e=[];while(!a(g)&&g!=document.body){e.push(g.expose()); +g=g.getParent();}var f=this.expose(),d=h.call(this);f();e.each(function(i){i();});return d;},expose:function(){if(this.getStyle("display")!="none"){return function(){}; +}var d=this.style.cssText;this.setStyles({display:"block",position:"absolute",visibility:"hidden"});return function(){this.style.cssText=d;}.bind(this); +},getDimensions:function(d){d=Object.merge({computeSize:false},d);var i={x:0,y:0};var h=function(j,e){return(e.computeSize)?j.getComputedSize(e):j.getSize(); +};var f=this.getParent("body");if(f&&this.getStyle("display")=="none"){i=this.measure(function(){return h(this,d);});}else{if(f){try{i=h(this,d);}catch(g){}}}return Object.append(i,(i.x||i.x===0)?{width:i.x,height:i.y}:{x:i.width,y:i.height}); +},getComputedSize:function(d){d=Object.merge({styles:["padding","border"],planes:{height:["top","bottom"],width:["left","right"]},mode:"both"},d);var g={},e={width:0,height:0},f; +if(d.mode=="vertical"){delete e.width;delete d.planes.width;}else{if(d.mode=="horizontal"){delete e.height;delete d.planes.height;}}b(d.styles,d.planes).each(function(h){g[h]=this.getStyle(h).toInt(); +},this);Object.each(d.planes,function(i,h){var k=h.capitalize(),j=this.getStyle(h);if(j=="auto"&&!f){f=this.getDimensions();}j=g[h]=(j=="auto")?f[h]:j.toInt(); +e["total"+k]=j;i.each(function(m){var l=c(m,g);e["computed"+m.capitalize()]=l;e["total"+k]+=l;});},this);return Object.append(e,g);}});})();(function(b){var a=Element.Position={options:{relativeTo:document.body,position:{x:"center",y:"center"},offset:{x:0,y:0}},getOptions:function(d,c){c=Object.merge({},a.options,c); +a.setPositionOption(c);a.setEdgeOption(c);a.setOffsetOption(d,c);a.setDimensionsOption(d,c);return c;},setPositionOption:function(c){c.position=a.getCoordinateFromValue(c.position); +},setEdgeOption:function(d){var c=a.getCoordinateFromValue(d.edge);d.edge=c?c:(d.position.x=="center"&&d.position.y=="center")?{x:"center",y:"center"}:{x:"left",y:"top"}; +},setOffsetOption:function(f,d){var c={x:0,y:0};var e={x:0,y:0};var g=f.measure(function(){return document.id(this.getOffsetParent());});if(!g||g==f.getDocument().body){return; +}e=g.getScroll();c=g.measure(function(){var i=this.getPosition();if(this.getStyle("position")=="fixed"){var h=window.getScroll();i.x+=h.x;i.y+=h.y;}return i; +});d.offset={parentPositioned:g!=document.id(d.relativeTo),x:d.offset.x-c.x+e.x,y:d.offset.y-c.y+e.y};},setDimensionsOption:function(d,c){c.dimensions=d.getDimensions({computeSize:true,styles:["padding","border","margin"]}); +},getPosition:function(e,d){var c={};d=a.getOptions(e,d);var f=document.id(d.relativeTo)||document.body;a.setPositionCoordinates(d,c,f);if(d.edge){a.toEdge(c,d); +}var g=d.offset;c.left=((c.x>=0||g.parentPositioned||d.allowNegative)?c.x:0).toInt();c.top=((c.y>=0||g.parentPositioned||d.allowNegative)?c.y:0).toInt(); +a.toMinMax(c,d);if(d.relFixedPosition||f.getStyle("position")=="fixed"){a.toRelFixedPosition(f,c);}if(d.ignoreScroll){a.toIgnoreScroll(f,c);}if(d.ignoreMargins){a.toIgnoreMargins(c,d); +}c.left=Math.ceil(c.left);c.top=Math.ceil(c.top);delete c.x;delete c.y;return c;},setPositionCoordinates:function(k,g,d){var f=k.offset.y,h=k.offset.x,e=(d==document.body)?window.getScroll():d.getPosition(),j=e.y,c=e.x,i=window.getSize(); +switch(k.position.x){case"left":g.x=c+h;break;case"right":g.x=c+h+d.offsetWidth;break;default:g.x=c+((d==document.body?i.x:d.offsetWidth)/2)+h;break;}switch(k.position.y){case"top":g.y=j+f; +break;case"bottom":g.y=j+f+d.offsetHeight;break;default:g.y=j+((d==document.body?i.y:d.offsetHeight)/2)+f;break;}},toMinMax:function(c,d){var f={left:"x",top:"y"},e; +["minimum","maximum"].each(function(g){["left","top"].each(function(h){e=d[g]?d[g][f[h]]:null;if(e!=null&&((g=="minimum")?c[h]<e:c[h]>e)){c[h]=e;}});}); +},toRelFixedPosition:function(e,c){var d=window.getScroll();c.top+=d.y;c.left+=d.x;},toIgnoreScroll:function(e,d){var c=e.getScroll();d.top-=c.y;d.left-=c.x; +},toIgnoreMargins:function(c,d){c.left+=d.edge.x=="right"?d.dimensions["margin-right"]:(d.edge.x!="center"?-d.dimensions["margin-left"]:-d.dimensions["margin-left"]+((d.dimensions["margin-right"]+d.dimensions["margin-left"])/2)); +c.top+=d.edge.y=="bottom"?d.dimensions["margin-bottom"]:(d.edge.y!="center"?-d.dimensions["margin-top"]:-d.dimensions["margin-top"]+((d.dimensions["margin-bottom"]+d.dimensions["margin-top"])/2)); +},toEdge:function(c,d){var e={},g=d.dimensions,f=d.edge;switch(f.x){case"left":e.x=0;break;case"right":e.x=-g.x-g.computedRight-g.computedLeft;break;default:e.x=-(Math.round(g.totalWidth/2)); +break;}switch(f.y){case"top":e.y=0;break;case"bottom":e.y=-g.y-g.computedTop-g.computedBottom;break;default:e.y=-(Math.round(g.totalHeight/2));break;}c.x+=e.x; +c.y+=e.y;},getCoordinateFromValue:function(c){if(typeOf(c)!="string"){return c;}c=c.toLowerCase();return{x:c.test("left")?"left":(c.test("right")?"right":"center"),y:c.test(/upper|top/)?"top":(c.test("bottom")?"bottom":"center")}; +}};Element.implement({position:function(d){if(d&&(d.x!=null||d.y!=null)){return(b?b.apply(this,arguments):this);}var c=this.setStyle("position","absolute").calculatePosition(d); +return(d&&d.returnPos)?c:this.setStyles(c);},calculatePosition:function(c){return a.getPosition(this,c);}});})(Element.prototype.position);(function(){var a=false; +this.IframeShim=new Class({Implements:[Options,Events,Class.Occlude],options:{className:"iframeShim",src:'javascript:false;document.write("");',display:false,zIndex:null,margin:0,offset:{x:0,y:0},browsers:a},property:"IframeShim",initialize:function(c,b){this.element=document.id(c); +if(this.occlude()){return this.occluded;}this.setOptions(b);this.makeShim();return this;},makeShim:function(){if(this.options.browsers){var d=this.element.getStyle("zIndex").toInt(); +if(!d){d=1;var c=this.element.getStyle("position");if(c=="static"||!c){this.element.setStyle("position","relative");}this.element.setStyle("zIndex",d); +}d=((this.options.zIndex!=null||this.options.zIndex===0)&&d>this.options.zIndex)?this.options.zIndex:d-1;if(d<0){d=1;}this.shim=new Element("iframe",{src:this.options.src,scrolling:"no",frameborder:0,styles:{zIndex:d,position:"absolute",border:"none",filter:"progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"},"class":this.options.className}).store("IframeShim",this); +var b=(function(){this.shim.inject(this.element,"after");this[this.options.display?"show":"hide"]();this.fireEvent("inject");}).bind(this);if(!IframeShim.ready){window.addEvent("load",b); +}else{b();}}else{this.position=this.hide=this.show=this.dispose=Function.from(this);}},position:function(){if(!IframeShim.ready||!this.shim){return this; +}var b=this.element.measure(function(){return this.getSize();});if(this.options.margin!=undefined){b.x=b.x-(this.options.margin*2);b.y=b.y-(this.options.margin*2); +this.options.offset.x+=this.options.margin;this.options.offset.y+=this.options.margin;}this.shim.set({width:b.x,height:b.y}).position({relativeTo:this.element,offset:this.options.offset}); +return this;},hide:function(){if(this.shim){this.shim.setStyle("display","none");}return this;},show:function(){if(this.shim){this.shim.setStyle("display","block"); +}return this.position();},dispose:function(){if(this.shim){this.shim.dispose();}return this;},destroy:function(){if(this.shim){this.shim.destroy();}return this; +}});})();window.addEvent("load",function(){IframeShim.ready=true;});var Mask=new Class({Implements:[Options,Events],Binds:["position"],options:{style:{},"class":"mask",maskMargins:false,useIframeShim:true,iframeShimOptions:{}},initialize:function(b,a){this.target=document.id(b)||document.id(document.body); +this.target.store("mask",this);this.setOptions(a);this.render();this.inject();},render:function(){this.element=new Element("div",{"class":this.options["class"],id:this.options.id||"mask-"+String.uniqueID(),styles:Object.merge({},this.options.style,{display:"none"}),events:{click:function(a){this.fireEvent("click",a); +if(this.options.hideOnClick){this.hide();}}.bind(this)}});this.hidden=true;},toElement:function(){return this.element;},inject:function(b,a){a=a||(this.options.inject?this.options.inject.where:"")||(this.target==document.body?"inside":"after"); +b=b||(this.options.inject&&this.options.inject.target)||this.target;this.element.inject(b,a);if(this.options.useIframeShim){this.shim=new IframeShim(this.element,this.options.iframeShimOptions); +this.addEvents({show:this.shim.show.bind(this.shim),hide:this.shim.hide.bind(this.shim),destroy:this.shim.destroy.bind(this.shim)});}},position:function(){this.resize(this.options.width,this.options.height); +this.element.position({relativeTo:this.target,position:"topLeft",ignoreMargins:!this.options.maskMargins,ignoreScroll:this.target==document.body});return this; +},resize:function(a,e){var b={styles:["padding","border"]};if(this.options.maskMargins){b.styles.push("margin");}var d=this.target.getComputedSize(b);if(this.target==document.body){this.element.setStyles({width:0,height:0}); +var c=window.getScrollSize();if(d.totalHeight<c.y){d.totalHeight=c.y;}if(d.totalWidth<c.x){d.totalWidth=c.x;}}this.element.setStyles({width:Array.pick([a,d.totalWidth,d.x]),height:Array.pick([e,d.totalHeight,d.y])}); +return this;},show:function(){if(!this.hidden){return this;}window.addEvent("resize",this.position);this.position();this.showMask.apply(this,arguments); +return this;},showMask:function(){this.element.setStyle("display","block");this.hidden=false;this.fireEvent("show");},hide:function(){if(this.hidden){return this; +}window.removeEvent("resize",this.position);this.hideMask.apply(this,arguments);if(this.options.destroyOnHide){return this.destroy();}return this;},hideMask:function(){this.element.setStyle("display","none"); +this.hidden=true;this.fireEvent("hide");},toggle:function(){this[this.hidden?"show":"hide"]();},destroy:function(){this.hide();this.element.destroy();this.fireEvent("destroy"); +this.target.eliminate("mask");}});Element.Properties.mask={set:function(b){var a=this.retrieve("mask");if(a){a.destroy();}return this.eliminate("mask").store("mask:options",b); +},get:function(){var a=this.retrieve("mask");if(!a){a=new Mask(this,this.retrieve("mask:options"));this.store("mask",a);}return a;}};Element.implement({mask:function(a){if(a){this.set("mask",a); +}this.get("mask").show();return this;},unmask:function(){this.get("mask").hide();return this;}});var Spinner=new Class({Extends:Mask,Implements:Chain,options:{"class":"spinner",containerPosition:{},content:{"class":"spinner-content"},messageContainer:{"class":"spinner-msg"},img:{"class":"spinner-img"},fxOptions:{link:"chain"}},initialize:function(c,a){this.target=document.id(c)||document.id(document.body); +this.target.store("spinner",this);this.setOptions(a);this.render();this.inject();var b=function(){this.active=false;}.bind(this);this.addEvents({hide:b,show:b}); +},render:function(){this.parent();this.element.set("id",this.options.id||"spinner-"+String.uniqueID());this.content=document.id(this.options.content)||new Element("div",this.options.content); +this.content.inject(this.element);if(this.options.message){this.msg=document.id(this.options.message)||new Element("p",this.options.messageContainer).appendText(this.options.message); +this.msg.inject(this.content);}if(this.options.img){this.img=document.id(this.options.img)||new Element("div",this.options.img);this.img.inject(this.content); +}this.element.set("tween",this.options.fxOptions);},show:function(a){if(this.active){return this.chain(this.show.bind(this));}if(!this.hidden){this.callChain.delay(20,this); +return this;}this.target.set("aria-busy","true");this.active=true;return this.parent(a);},showMask:function(a){var b=function(){this.content.position(Object.merge({relativeTo:this.element},this.options.containerPosition)); +}.bind(this);if(a){this.parent();b();}else{if(!this.options.style.opacity){this.options.style.opacity=this.element.getStyle("opacity").toFloat();}this.element.setStyles({display:"block",opacity:0}).tween("opacity",this.options.style.opacity); +b();this.hidden=false;this.fireEvent("show");this.callChain();}},hide:function(a){if(this.active){return this.chain(this.hide.bind(this));}if(this.hidden){this.callChain.delay(20,this); +return this;}this.target.set("aria-busy","false");this.active=true;return this.parent(a);},hideMask:function(a){if(a){return this.parent();}this.element.tween("opacity",0).get("tween").chain(function(){this.element.setStyle("display","none"); +this.hidden=true;this.fireEvent("hide");this.callChain();}.bind(this));},destroy:function(){this.content.destroy();this.parent();this.target.eliminate("spinner"); +}});Request=Class.refactor(Request,{options:{useSpinner:false,spinnerOptions:{},spinnerTarget:false},initialize:function(a){this._send=this.send;this.send=function(b){var c=this.getSpinner(); +if(c){c.chain(this._send.pass(b,this)).show();}else{this._send(b);}return this;};this.previous(a);},getSpinner:function(){if(!this.spinner){var b=document.id(this.options.spinnerTarget)||document.id(this.options.update); +if(this.options.useSpinner&&b){b.set("spinner",this.options.spinnerOptions);var a=this.spinner=b.get("spinner");["complete","exception","cancel"].each(function(c){this.addEvent(c,a.hide.bind(a)); +},this);}}return this.spinner;}});Element.Properties.spinner={set:function(a){var b=this.retrieve("spinner");if(b){b.destroy();}return this.eliminate("spinner").store("spinner:options",a); +},get:function(){var a=this.retrieve("spinner");if(!a){a=new Spinner(this,this.retrieve("spinner:options"));this.store("spinner",a);}return a;}};Element.implement({spin:function(a){if(a){this.set("spinner",a); +}this.get("spinner").show();return this;},unspin:function(){this.get("spinner").hide();return this;}});String.implement({parseQueryString:function(d,a){if(d==null){d=true; +}if(a==null){a=true;}var c=this.split(/[&;]/),b={};if(!c.length){return b;}c.each(function(i){var e=i.indexOf("=")+1,g=e?i.substr(e):"",f=e?i.substr(0,e-1).match(/([^\]\[]+|(\B)(?=\]))/g):[i],h=b; +if(!f){return;}if(a){g=decodeURIComponent(g);}f.each(function(k,j){if(d){k=decodeURIComponent(k);}var l=h[k];if(j<f.length-1){h=h[k]=l||{};}else{if(typeOf(l)=="array"){l.push(g); +}else{h[k]=l!=null?[l,g]:g;}}});});return b;},cleanQueryString:function(a){return this.split("&").filter(function(e){var b=e.indexOf("="),c=b<0?"":e.substr(0,b),d=e.substr(b+1); +return a?a.call(null,c,d):(d||d===0);}).join("&");}});(function(){Events.Pseudos=function(h,e,f){var d="_monitorEvents:";var c=function(i){return{store:i.store?function(j,k){i.store(d+j,k); +}:function(j,k){(i._monitorEvents||(i._monitorEvents={}))[j]=k;},retrieve:i.retrieve?function(j,k){return i.retrieve(d+j,k);}:function(j,k){if(!i._monitorEvents){return k; +}return i._monitorEvents[j]||k;}};};var g=function(k){if(k.indexOf(":")==-1||!h){return null;}var j=Slick.parse(k).expressions[0][0],p=j.pseudos,i=p.length,o=[]; +while(i--){var n=p[i].key,m=h[n];if(m!=null){o.push({event:j.tag,value:p[i].value,pseudo:n,original:k,listener:m});}}return o.length?o:null;};return{addEvent:function(m,p,j){var n=g(m); +if(!n){return e.call(this,m,p,j);}var k=c(this),r=k.retrieve(m,[]),i=n[0].event,l=Array.slice(arguments,2),o=p,q=this;n.each(function(s){var t=s.listener,u=o; +if(t==false){i+=":"+s.pseudo+"("+s.value+")";}else{o=function(){t.call(q,s,u,arguments,o);};}});r.include({type:i,event:p,monitor:o});k.store(m,r);if(m!=i){e.apply(this,[m,p].concat(l)); +}return e.apply(this,[i,o].concat(l));},removeEvent:function(m,l){var k=g(m);if(!k){return f.call(this,m,l);}var n=c(this),j=n.retrieve(m);if(!j){return this; +}var i=Array.slice(arguments,2);f.apply(this,[m,l].concat(i));j.each(function(o,p){if(!l||o.event==l){f.apply(this,[o.type,o.monitor].concat(i));}delete j[p]; +},this);n.store(m,j);return this;}};};var b={once:function(e,f,d,c){f.apply(this,d);this.removeEvent(e.event,c).removeEvent(e.original,f);},throttle:function(d,e,c){if(!e._throttled){e.apply(this,c); +e._throttled=setTimeout(function(){e._throttled=false;},d.value||250);}},pause:function(d,e,c){clearTimeout(e._pause);e._pause=e.delay(d.value||250,this,c); +}};Events.definePseudo=function(c,d){b[c]=d;return this;};Events.lookupPseudo=function(c){return b[c];};var a=Events.prototype;Events.implement(Events.Pseudos(b,a.addEvent,a.removeEvent)); +["Request","Fx"].each(function(c){if(this[c]){this[c].implement(Events.prototype);}});})();(function(){var d={relay:false},c=["once","throttle","pause"],b=c.length; +while(b--){d[c[b]]=Events.lookupPseudo(c[b]);}DOMEvent.definePseudo=function(e,f){d[e]=f;return this;};var a=Element.prototype;[Element,Window,Document].invoke("implement",Events.Pseudos(d,a.addEvent,a.removeEvent)); +})();if(!window.Form){window.Form={};}(function(){Form.Request=new Class({Binds:["onSubmit","onFormValidate"],Implements:[Options,Events,Class.Occlude],options:{requestOptions:{evalScripts:true,useSpinner:true,emulation:false,link:"ignore"},sendButtonClicked:true,extraData:{},resetForm:true},property:"form.request",initialize:function(b,c,a){this.element=document.id(b); +if(this.occlude()){return this.occluded;}this.setOptions(a).setTarget(c).attach();},setTarget:function(a){this.target=document.id(a);if(!this.request){this.makeRequest(); +}else{this.request.setOptions({update:this.target});}return this;},toElement:function(){return this.element;},makeRequest:function(){var a=this;this.request=new Request.HTML(Object.merge({update:this.target,emulation:false,spinnerTarget:this.element,method:this.element.get("method")||"post"},this.options.requestOptions)).addEvents({success:function(c,e,d,b){["complete","success"].each(function(f){a.fireEvent(f,[a.target,c,e,d,b]); +});},failure:function(){a.fireEvent("complete",arguments).fireEvent("failure",arguments);},exception:function(){a.fireEvent("failure",arguments);}});return this.attachReset(); +},attachReset:function(){if(!this.options.resetForm){return this;}this.request.addEvent("success",function(){Function.attempt(function(){this.element.reset(); +}.bind(this));if(window.OverText){OverText.update();}}.bind(this));return this;},attach:function(a){var c=(a!=false)?"addEvent":"removeEvent";this.element[c]("click:relay(button, input[type=submit])",this.saveClickedButton.bind(this)); +var b=this.element.retrieve("validator");if(b){b[c]("onFormValidate",this.onFormValidate);}else{this.element[c]("submit",this.onSubmit);}return this;},detach:function(){return this.attach(false); +},enable:function(){return this.attach();},disable:function(){return this.detach();},onFormValidate:function(c,b,a){if(!a){return;}var d=this.element.retrieve("validator"); +if(c||(d&&!d.options.stopOnFailure)){a.stop();this.send();}},onSubmit:function(a){var b=this.element.retrieve("validator");if(b){this.element.removeEvent("submit",this.onSubmit); +b.addEvent("onFormValidate",this.onFormValidate);b.validate(a);return;}if(a){a.stop();}this.send();},saveClickedButton:function(b,c){var a=c.get("name"); +if(!a||!this.options.sendButtonClicked){return;}this.options.extraData[a]=c.get("value")||true;this.clickedCleaner=function(){delete this.options.extraData[a]; +this.clickedCleaner=function(){};}.bind(this);},clickedCleaner:function(){},send:function(){var b=this.element.toQueryString().trim(),a=Object.toQueryString(this.options.extraData); +if(b){b+="&"+a;}else{b=a;}this.fireEvent("send",[this.element,b.parseQueryString()]);this.request.send({data:b,url:this.options.requestOptions.url||this.element.get("action")}); +this.clickedCleaner();return this;}});Element.implement("formUpdate",function(c,b){var a=this.retrieve("form.request");if(!a){a=new Form.Request(this,c,b); +}else{if(c){a.setTarget(c);}if(b){a.setOptions(b).makeRequest();}}a.send();return this;});})();Element.implement({isDisplayed:function(){return this.getStyle("display")!="none"; +},isVisible:function(){var a=this.offsetWidth,b=this.offsetHeight;return(a==0&&b==0)?false:(a>0&&b>0)?true:this.style.display!="none";},toggle:function(){return this[this.isDisplayed()?"hide":"show"](); +},hide:function(){var b;try{b=this.getStyle("display");}catch(a){}if(b=="none"){return this;}return this.store("element:_originalDisplay",b||"").setStyle("display","none"); +},show:function(a){if(!a&&this.isDisplayed()){return this;}a=a||this.retrieve("element:_originalDisplay")||"block";return this.setStyle("display",(a=="none")?"block":a); +},swapClass:function(a,b){return this.removeClass(a).addClass(b);}});Document.implement({clearSelection:function(){if(window.getSelection){var a=window.getSelection(); +if(a&&a.removeAllRanges){a.removeAllRanges();}}else{if(document.selection&&document.selection.empty){try{document.selection.empty();}catch(b){}}}}});(function(){var a=function(d){var b=d.options.hideInputs; +if(window.OverText){var c=[null];OverText.each(function(e){c.include("."+e.options.labelClass);});if(c){b+=c.join(", ");}}return(b)?d.element.getElements(b):null; +};Fx.Reveal=new Class({Extends:Fx.Morph,options:{link:"cancel",styles:["padding","border","margin"],transitionOpacity:"opacity" in document.documentElement,mode:"vertical",display:function(){return this.element.get("tag")!="tr"?"block":"table-row"; +},opacity:1,hideInputs:!("opacity" in document.documentElement)?"select, input, textarea, object, embed":null},dissolve:function(){if(!this.hiding&&!this.showing){if(this.element.getStyle("display")!="none"){this.hiding=true; +this.showing=false;this.hidden=true;this.cssText=this.element.style.cssText;var d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode}); +if(this.options.transitionOpacity){d.opacity=this.options.opacity;}var c={};Object.each(d,function(f,e){c[e]=[f,0];});this.element.setStyles({display:Function.from(this.options.display).call(this),overflow:"hidden"}); +var b=a(this);if(b){b.setStyle("visibility","hidden");}this.$chain.unshift(function(){if(this.hidden){this.hiding=false;this.element.style.cssText=this.cssText; +this.element.setStyle("display","none");if(b){b.setStyle("visibility","visible");}}this.fireEvent("hide",this.element);this.callChain();}.bind(this));this.start(c); +}else{this.callChain.delay(10,this);this.fireEvent("complete",this.element);this.fireEvent("hide",this.element);}}else{if(this.options.link=="chain"){this.chain(this.dissolve.bind(this)); +}else{if(this.options.link=="cancel"&&!this.hiding){this.cancel();this.dissolve();}}}return this;},reveal:function(){if(!this.showing&&!this.hiding){if(this.element.getStyle("display")=="none"){this.hiding=false; +this.showing=true;this.hidden=false;this.cssText=this.element.style.cssText;var d;this.element.measure(function(){d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode}); +}.bind(this));if(this.options.heightOverride!=null){d.height=this.options.heightOverride.toInt();}if(this.options.widthOverride!=null){d.width=this.options.widthOverride.toInt(); +}if(this.options.transitionOpacity){this.element.setStyle("opacity",0);d.opacity=this.options.opacity;}var c={height:0,display:Function.from(this.options.display).call(this)}; +Object.each(d,function(f,e){c[e]=0;});c.overflow="hidden";this.element.setStyles(c);var b=a(this);if(b){b.setStyle("visibility","hidden");}this.$chain.unshift(function(){this.element.style.cssText=this.cssText; +this.element.setStyle("display",Function.from(this.options.display).call(this));if(!this.hidden){this.showing=false;}if(b){b.setStyle("visibility","visible"); +}this.callChain();this.fireEvent("show",this.element);}.bind(this));this.start(d);}else{this.callChain();this.fireEvent("complete",this.element);this.fireEvent("show",this.element); +}}else{if(this.options.link=="chain"){this.chain(this.reveal.bind(this));}else{if(this.options.link=="cancel"&&!this.showing){this.cancel();this.reveal(); +}}}return this;},toggle:function(){if(this.element.getStyle("display")=="none"){this.reveal();}else{this.dissolve();}return this;},cancel:function(){this.parent.apply(this,arguments); +if(this.cssText!=null){this.element.style.cssText=this.cssText;}this.hiding=false;this.showing=false;return this;}});Element.Properties.reveal={set:function(b){this.get("reveal").cancel().setOptions(b); +return this;},get:function(){var b=this.retrieve("reveal");if(!b){b=new Fx.Reveal(this);this.store("reveal",b);}return b;}};Element.Properties.dissolve=Element.Properties.reveal; +Element.implement({reveal:function(b){this.get("reveal").setOptions(b).reveal();return this;},dissolve:function(b){this.get("reveal").setOptions(b).dissolve(); +return this;},nix:function(b){var c=Array.link(arguments,{destroy:Type.isBoolean,options:Type.isObject});this.get("reveal").setOptions(b).dissolve().chain(function(){this[c.destroy?"destroy":"dispose"](); +}.bind(this));return this;},wink:function(){var c=Array.link(arguments,{duration:Type.isNumber,options:Type.isObject});var b=this.get("reveal").setOptions(c.options); +b.reveal().chain(function(){(function(){b.dissolve();}).delay(c.duration||2000);});}});})();var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var b=Array.link(arguments,{options:Type.isObject,element:function(c){return c!=null; +}});this.element=document.id(b.element);this.document=this.element.getDocument();this.setOptions(b.options||{});var a=typeOf(this.options.handle);this.handles=((a=="array"||a=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element; +this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection="selectstart" in document?"selectstart":"mousedown";if("ondragstart" in document&&!("FileReader" in window)&&!Drag.ondragstartFixed){document.ondragstart=Function.from(false); +Drag.ondragstartFixed=true;}this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:Function.from(false)}; +this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start); +return this;},start:function(a){var j=this.options;if(a.rightClick){return;}if(j.preventDefault){a.preventDefault();}if(j.stopPropagation){a.stopPropagation(); +}this.mouse.start=a.page;this.fireEvent("beforeStart",this.element);var c=j.limit;this.limit={x:[],y:[]};var e,g;for(e in j.modifiers){if(!j.modifiers[e]){continue; +}var b=this.element.getStyle(j.modifiers[e]);if(b&&!b.match(/px$/)){if(!g){g=this.element.getCoordinates(this.element.getOffsetParent());}b=g[j.modifiers[e]]; +}if(j.style){this.value.now[e]=(b||0).toInt();}else{this.value.now[e]=this.element[j.modifiers[e]];}if(j.invert){this.value.now[e]*=-1;}this.mouse.pos[e]=a.page[e]-this.value.now[e]; +if(c&&c[e]){var d=2;while(d--){var f=c[e][d];if(f||f===0){this.limit[e][d]=(typeof f=="function")?f():f;}}}}if(typeOf(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}; +}var h={mousemove:this.bound.check,mouseup:this.bound.cancel};h[this.selection]=this.bound.eventStop;this.document.addEvents(h);},check:function(a){if(this.options.preventDefault){a.preventDefault(); +}var b=Math.round(Math.sqrt(Math.pow(a.page.x-this.mouse.start.x,2)+Math.pow(a.page.y-this.mouse.start.y,2)));if(b>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop}); +this.fireEvent("start",[this.element,a]).fireEvent("snap",this.element);}},drag:function(b){var a=this.options;if(a.preventDefault){b.preventDefault(); +}this.mouse.now=b.page;for(var c in a.modifiers){if(!a.modifiers[c]){continue;}this.value.now[c]=this.mouse.now[c]-this.mouse.pos[c];if(a.invert){this.value.now[c]*=-1; +}if(a.limit&&this.limit[c]){if((this.limit[c][1]||this.limit[c][1]===0)&&(this.value.now[c]>this.limit[c][1])){this.value.now[c]=this.limit[c][1];}else{if((this.limit[c][0]||this.limit[c][0]===0)&&(this.value.now[c]<this.limit[c][0])){this.value.now[c]=this.limit[c][0]; +}}}if(a.grid[c]){this.value.now[c]-=((this.value.now[c]-(this.limit[c][0]||0))%a.grid[c]);}if(a.style){this.element.setStyle(a.modifiers[c],this.value.now[c]+a.unit); +}else{this.element[a.modifiers[c]]=this.value.now[c];}}this.fireEvent("drag",[this.element,b]);},cancel:function(a){this.document.removeEvents({mousemove:this.bound.check,mouseup:this.bound.cancel}); +if(a){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element);}},stop:function(b){var a={mousemove:this.bound.drag,mouseup:this.bound.stop}; +a[this.selection]=this.bound.eventStop;this.document.removeEvents(a);if(b){this.fireEvent("complete",[this.element,b]);}}});Element.implement({makeResizable:function(a){var b=new Drag(this,Object.merge({modifiers:{x:"width",y:"height"}},a)); +this.store("resizer",b);return b.addEvent("drag",function(){this.fireEvent("resize",b);}.bind(this));}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false,precalculate:false,includeMargins:true,checkDroppables:true},initialize:function(b,a){this.parent(b,a); +b=this.element;this.droppables=$$(this.options.droppables);this.setContainer(this.options.container);if(this.options.style){if(this.options.modifiers.x=="left"&&this.options.modifiers.y=="top"){var c=b.getOffsetParent(),d=b.getStyles("left","top"); +if(c&&(d.left=="auto"||d.top=="auto")){b.setPosition(b.getPosition(c));}}if(b.getStyle("position")=="static"){b.setStyle("position","absolute");}}this.addEvent("start",this.checkDroppables,true); +this.overed=null;},setContainer:function(a){this.container=document.id(a);if(this.container&&typeOf(this.container)!="element"){this.container=document.id(this.container.getDocument().body); +}},start:function(a){if(this.container){this.options.limit=this.calculateLimit();}if(this.options.precalculate){this.positions=this.droppables.map(function(b){return b.getCoordinates(); +});}this.parent(a);},calculateLimit:function(){var j=this.element,e=this.container,d=document.id(j.getOffsetParent())||document.body,h=e.getCoordinates(d),c={},b={},k={},g={},m={}; +["top","right","bottom","left"].each(function(q){c[q]=j.getStyle("margin-"+q).toInt();b[q]=j.getStyle("border-"+q).toInt();k[q]=e.getStyle("margin-"+q).toInt(); +g[q]=e.getStyle("border-"+q).toInt();m[q]=d.getStyle("padding-"+q).toInt();},this);var f=j.offsetWidth+c.left+c.right,p=j.offsetHeight+c.top+c.bottom,i=0,l=0,o=h.right-g.right-f,a=h.bottom-g.bottom-p; +if(this.options.includeMargins){i+=c.left;l+=c.top;}else{o+=c.right;a+=c.bottom;}if(j.getStyle("position")=="relative"){var n=j.getCoordinates(d);n.left-=j.getStyle("left").toInt(); +n.top-=j.getStyle("top").toInt();i-=n.left;l-=n.top;if(e.getStyle("position")!="relative"){i+=g.left;l+=g.top;}o+=c.left-n.left;a+=c.top-n.top;if(e!=d){i+=k.left+m.left; +if(!m.left&&i<0){i=0;}l+=d==document.body?0:k.top+m.top;if(!m.top&&l<0){l=0;}}}else{i-=c.left;l-=c.top;if(e!=d){i+=h.left+g.left;l+=h.top+g.top;}}return{x:[i,o],y:[l,a]}; +},getDroppableCoordinates:function(c){var b=c.getCoordinates();if(c.getStyle("position")=="fixed"){var a=window.getScroll();b.left+=a.x;b.right+=a.x;b.top+=a.y; +b.bottom+=a.y;}return b;},checkDroppables:function(){var a=this.droppables.filter(function(d,c){d=this.positions?this.positions[c]:this.getDroppableCoordinates(d); +var b=this.mouse.now;return(b.x>d.left&&b.x<d.right&&b.y<d.bottom&&b.y>d.top);},this).getLast();if(this.overed!=a){if(this.overed){this.fireEvent("leave",[this.element,this.overed]); +}if(a){this.fireEvent("enter",[this.element,a]);}this.overed=a;}},drag:function(a){this.parent(a);if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables(); +}},stop:function(a){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,a]);this.overed=null;return this.parent(a);}});Element.implement({makeDraggable:function(a){var b=new Drag.Move(this,a); +this.store("dragger",b);return b;}});var Sortables=new Class({Implements:[Events,Options],options:{opacity:1,clone:false,revert:false,handle:false,dragOptions:{},unDraggableTags:["button","input","a","textarea","select","option"]},initialize:function(a,b){this.setOptions(b); +this.elements=[];this.lists=[];this.idle=true;this.addLists($$(document.id(a)||a));if(!this.options.clone){this.options.revert=false;}if(this.options.revert){this.effect=new Fx.Morph(null,Object.merge({duration:250,link:"cancel"},this.options.revert)); +}},attach:function(){this.addLists(this.lists);return this;},detach:function(){this.lists=this.removeLists(this.lists);return this;},addItems:function(){Array.flatten(arguments).each(function(a){this.elements.push(a); +var b=a.retrieve("sortables:start",function(c){this.start.call(this,c,a);}.bind(this));(this.options.handle?a.getElement(this.options.handle)||a:a).addEvent("mousedown",b); +},this);return this;},addLists:function(){Array.flatten(arguments).each(function(a){this.lists.include(a);this.addItems(a.getChildren());},this);return this; +},removeItems:function(){return $$(Array.flatten(arguments).map(function(a){this.elements.erase(a);var b=a.retrieve("sortables:start");(this.options.handle?a.getElement(this.options.handle)||a:a).removeEvent("mousedown",b); +return a;},this));},removeLists:function(){return $$(Array.flatten(arguments).map(function(a){this.lists.erase(a);this.removeItems(a.getChildren());return a; +},this));},getDroppableCoordinates:function(c){var d=c.getOffsetParent();var b=c.getPosition(d);var a={w:window.getScroll(),offsetParent:d.getScroll()}; +b.x+=a.offsetParent.x;b.y+=a.offsetParent.y;if(d.getStyle("position")=="fixed"){b.x-=a.w.x;b.y-=a.w.y;}return b;},getClone:function(b,a){if(!this.options.clone){return new Element(a.tagName).inject(document.body); +}if(typeOf(this.options.clone)=="function"){return this.options.clone.call(this,b,a,this.list);}var c=a.clone(true).setStyles({margin:0,position:"absolute",visibility:"hidden",width:a.getStyle("width")}).addEvent("mousedown",function(d){a.fireEvent("mousedown",d); +});if(c.get("html").test("radio")){c.getElements("input[type=radio]").each(function(d,e){d.set("name","clone_"+e);if(d.get("checked")){a.getElements("input[type=radio]")[e].set("checked",true); +}});}return c.inject(this.list).setPosition(this.getDroppableCoordinates(this.element));},getDroppables:function(){var a=this.list.getChildren().erase(this.clone).erase(this.element); +if(!this.options.constrain){a.append(this.lists).erase(this.list);}return a;},insert:function(c,b){var a="inside";if(this.lists.contains(b)){this.list=b; +this.drag.droppables=this.getDroppables();}else{a=this.element.getAllPrevious().contains(b)?"before":"after";}this.element.inject(b,a);this.fireEvent("sort",[this.element,this.clone]); +},start:function(b,a){if(!this.idle||b.rightClick||(!this.options.handle&&this.options.unDraggableTags.contains(b.target.get("tag")))){return;}this.idle=false; +this.element=a;this.opacity=a.getStyle("opacity");this.list=a.getParent();this.clone=this.getClone(b,a);this.drag=new Drag.Move(this.clone,Object.merge({droppables:this.getDroppables()},this.options.dragOptions)).addEvents({onSnap:function(){b.stop(); +this.clone.setStyle("visibility","visible");this.element.setStyle("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone]); +}.bind(this),onEnter:this.insert.bind(this),onCancel:this.end.bind(this),onComplete:this.end.bind(this)});this.clone.inject(this.element,"before");this.drag.start(b); +},end:function(){this.drag.detach();this.element.setStyle("opacity",this.opacity);var a=this;if(this.effect){var c=this.element.getStyles("width","height"),e=this.clone,d=e.computePosition(this.getDroppableCoordinates(e)); +var b=function(){this.removeEvent("cancel",b);e.destroy();a.reset();};this.effect.element=e;this.effect.start({top:d.top,left:d.left,width:c.width,height:c.height,opacity:0.25}).addEvent("cancel",b).chain(b); +}else{this.clone.destroy();a.reset();}},reset:function(){this.idle=true;this.fireEvent("complete",this.element);},serialize:function(){var c=Array.link(arguments,{modifier:Type.isFunction,index:function(d){return d!=null; +}});var b=this.lists.map(function(d){return d.getChildren().map(c.modifier||function(e){return e.get("id");},this);},this);var a=c.index;if(this.lists.length==1){a=0; +}return(a||a===0)&&a>=0&&a<this.lists.length?b[a]:b;}});Request.implement({options:{initialDelay:5000,delay:5000,limit:60000},startTimer:function(b){var a=function(){if(!this.running){this.send({data:b}); +}};this.lastDelay=this.options.initialDelay;this.timer=a.delay(this.lastDelay,this);this.completeCheck=function(c){clearTimeout(this.timer);this.lastDelay=(c)?this.options.delay:(this.lastDelay+this.options.delay).min(this.options.limit); +this.timer=a.delay(this.lastDelay,this);};return this.addEvent("complete",this.completeCheck);},stopTimer:function(){clearTimeout(this.timer);return this.removeEvent("complete",this.completeCheck); +}});(function(){var a=this.Color=new Type("Color",function(c,d){if(arguments.length>=3){d="rgb";c=Array.slice(arguments,0,3);}else{if(typeof c=="string"){if(c.match(/rgb/)){c=c.rgbToHex().hexToRgb(true); +}else{if(c.match(/hsb/)){c=c.hsbToRgb();}else{c=c.hexToRgb(true);}}}}d=d||"rgb";switch(d){case"hsb":var b=c;c=c.hsbToRgb();c.hsb=b;break;case"hex":c=c.hexToRgb(true); +break;}c.rgb=c.slice(0,3);c.hsb=c.hsb||c.rgbToHsb();c.hex=c.rgbToHex();return Object.append(c,this);});a.implement({mix:function(){var b=Array.slice(arguments); +var d=(typeOf(b.getLast())=="number")?b.pop():50;var c=this.slice();b.each(function(e){e=new a(e);for(var f=0;f<3;f++){c[f]=Math.round((c[f]/100*(100-d))+(e[f]/100*d)); +}});return new a(c,"rgb");},invert:function(){return new a(this.map(function(b){return 255-b;}));},setHue:function(b){return new a([b,this.hsb[1],this.hsb[2]],"hsb"); +},setSaturation:function(b){return new a([this.hsb[0],b,this.hsb[2]],"hsb");},setBrightness:function(b){return new a([this.hsb[0],this.hsb[1],b],"hsb"); +}});this.$RGB=function(e,d,c){return new a([e,d,c],"rgb");};this.$HSB=function(e,d,c){return new a([e,d,c],"hsb");};this.$HEX=function(b){return new a(b,"hex"); +};Array.implement({rgbToHsb:function(){var c=this[0],d=this[1],k=this[2],h=0;var j=Math.max(c,d,k),f=Math.min(c,d,k);var l=j-f;var i=j/255,g=(j!=0)?l/j:0; +if(g!=0){var e=(j-c)/l;var b=(j-d)/l;var m=(j-k)/l;if(c==j){h=m-b;}else{if(d==j){h=2+e-m;}else{h=4+b-e;}}h/=6;if(h<0){h++;}}return[Math.round(h*360),Math.round(g*100),Math.round(i*100)]; +},hsbToRgb:function(){var d=Math.round(this[2]/100*255);if(this[1]==0){return[d,d,d];}else{var b=this[0]%360;var g=b%60;var h=Math.round((this[2]*(100-this[1]))/10000*255); +var e=Math.round((this[2]*(6000-this[1]*g))/600000*255);var c=Math.round((this[2]*(6000-this[1]*(60-g)))/600000*255);switch(Math.floor(b/60)){case 0:return[d,c,h]; +case 1:return[e,d,h];case 2:return[h,d,c];case 3:return[h,e,d];case 4:return[c,h,d];case 5:return[d,h,e];}}return false;}});String.implement({rgbToHsb:function(){var b=this.match(/\d{1,3}/g); +return(b)?b.rgbToHsb():null;},hsbToRgb:function(){var b=this.match(/\d{1,3}/g);return(b)?b.hsbToRgb():null;}});})();
\ No newline at end of file diff --git a/module/webui/themes/flat/js/static/purr.js b/module/webui/themes/flat/js/static/purr.js new file mode 100644 index 000000000..9cbc503d9 --- /dev/null +++ b/module/webui/themes/flat/js/static/purr.js @@ -0,0 +1,309 @@ +/* +--- +script: purr.js + +description: Class to create growl-style popup notifications. + +license: MIT-style + +authors: [atom smith] + +requires: +- core/1.3: [Core, Browser, Array, Function, Number, String, Hash, Event, Class.Extras, Element.Event, Element.Style, Element.Dimensions, Fx.CSS, FX.Tween, Fx.Morph] + +provides: [Purr, Element.alert] +... +*/ + + +var Purr = new Class({ + + 'options': { + 'mode': 'top', + 'position': 'left', + 'elementAlertClass': 'purr-element-alert', + 'elements': { + 'wrapper': 'div', + 'alert': 'div', + 'buttonWrapper': 'div', + 'button': 'button' + }, + 'elementOptions': { + 'wrapper': { + 'styles': { + 'position': 'fixed', + 'z-index': '9999' + }, + 'class': 'purr-wrapper' + }, + 'alert': { + 'class': 'purr-alert', + 'styles': { + 'opacity': '.85' + } + }, + 'buttonWrapper': { + 'class': 'purr-button-wrapper' + }, + 'button': { + 'class': 'purr-button' + } + }, + 'alert': { + 'buttons': [], + 'clickDismiss': true, + 'hoverWait': true, + 'hideAfter': 5000, + 'fx': { + 'duration': 500 + }, + 'highlight': false, + 'highlightRepeat': false, + 'highlight': { + 'start': '#FF0', + 'end': false + } + } + }, + + 'Implements': [Options, Events, Chain], + + 'initialize': function(options){ + this.setOptions(options); + this.createWrapper(); + return this; + }, + + 'bindAlert': function(){ + return this.alert.bind(this); + }, + + 'createWrapper': function(){ + this.wrapper = new Element(this.options.elements.wrapper, this.options.elementOptions.wrapper); + if(this.options.mode == 'top') + { + this.wrapper.setStyle('top', 0); + } + else + { + this.wrapper.setStyle('bottom', 0); + } + document.id(document.body).grab(this.wrapper); + this.positionWrapper(this.options.position); + }, + + 'positionWrapper': function(position){ + if(typeOf(position) == 'object') + { + + var wrapperCoords = this.getWrapperCoords(); + + this.wrapper.setStyles({ + 'bottom': '', + 'left': position.x, + 'top': position.y - wrapperCoords.height, + 'position': 'absolute' + }); + } + else if(position == 'left') + { + this.wrapper.setStyle('left', 0); + } + else if(position == 'right') + { + this.wrapper.setStyle('right', 0); + } + else + { + this.wrapper.setStyle('left', (window.innerWidth / 2) - (this.getWrapperCoords().width / 2)); + } + return this; + }, + + 'getWrapperCoords': function(){ + this.wrapper.setStyle('visibility', 'hidden'); + var measurer = this.alert('need something in here to measure'); + var coords = this.wrapper.getCoordinates(); + measurer.destroy(); + this.wrapper.setStyle('visibility',''); + return coords; + }, + + 'alert': function(msg, options){ + + options = Object.merge({}, this.options.alert, options || {}); + + var alert = new Element(this.options.elements.alert, this.options.elementOptions.alert); + + if(typeOf(msg) == 'string') + { + alert.set('html', msg); + } + else if(typeOf(msg) == 'element') + { + alert.grab(msg); + } + else if(typeOf(msg) == 'array') + { + var alerts = []; + msg.each(function(m){ + alerts.push(this.alert(m, options)); + }, this); + return alerts; + } + + alert.store('options', options); + + if(options.buttons.length > 0) + { + options.clickDismiss = false; + options.hideAfter = false; + options.hoverWait = false; + var buttonWrapper = new Element(this.options.elements.buttonWrapper, this.options.elementOptions.buttonWrapper); + alert.grab(buttonWrapper); + options.buttons.each(function(button){ + if(button.text != undefined) + { + var callbackButton = new Element(this.options.elements.button, this.options.elementOptions.button); + callbackButton.set('html', button.text); + if(button.callback != undefined) + { + callbackButton.addEvent('click', button.callback.pass(alert)); + } + if(button.dismiss != undefined && button.dismiss) + { + callbackButton.addEvent('click', this.dismiss.pass(alert, this)); + } + buttonWrapper.grab(callbackButton); + } + }, this); + } + if(options.className != undefined) + { + alert.addClass(options.className); + } + + this.wrapper.grab(alert, (this.options.mode == 'top') ? 'bottom' : 'top'); + + var fx = Object.merge(this.options.alert.fx, options.fx); + var alertFx = new Fx.Morph(alert, fx); + alert.store('fx', alertFx); + this.fadeIn(alert); + + if(options.highlight) + { + alertFx.addEvent('complete', function(){ + alert.highlight(options.highlight.start, options.highlight.end); + if(options.highlightRepeat) + { + alert.highlight.periodical(options.highlightRepeat, alert, [options.highlight.start, options.highlight.end]); + } + }); + } + if(options.hideAfter) + { + this.dismiss(alert); + } + + if(options.clickDismiss) + { + alert.addEvent('click', function(){ + this.holdUp = false; + this.dismiss(alert, true); + }.bind(this)); + } + + if(options.hoverWait) + { + alert.addEvents({ + 'mouseenter': function(){ + this.holdUp = true; + }.bind(this), + 'mouseleave': function(){ + this.holdUp = false; + }.bind(this) + }); + } + + return alert; + }, + + 'fadeIn': function(alert){ + var alertFx = alert.retrieve('fx'); + alertFx.set({ + 'opacity': 0 + }); + alertFx.start({ + 'opacity': [this.options.elementOptions.alert.styles.opacity, .9].pick(), + }); + }, + + 'dismiss': function(alert, now){ + now = now || false; + var options = alert.retrieve('options'); + if(now) + { + this.fadeOut(alert); + } + else + { + this.fadeOut.delay(options.hideAfter, this, alert); + } + }, + + 'fadeOut': function(alert){ + if(this.holdUp) + { + this.dismiss.delay(100, this, [alert, true]) + return null; + } + var alertFx = alert.retrieve('fx'); + if(!alertFx) + { + return null; + } + var to = { + 'opacity': 0 + } + if(this.options.mode == 'top') + { + to['margin-top'] = '-'+alert.offsetHeight+'px'; + } + else + { + to['margin-bottom'] = '-'+alert.offsetHeight+'px'; + } + alertFx.start(to); + alertFx.addEvent('complete', function(){ + alert.destroy(); + }); + } +}); + +Element.implement({ + + 'alert': function(msg, options){ + var alert = this.retrieve('alert'); + if(!alert) + { + options = options || { + 'mode':'top' + }; + alert = new Purr(options) + this.store('alert', alert); + } + + var coords = this.getCoordinates(); + + alert.alert(msg, options); + + alert.wrapper.setStyles({ + 'bottom': '', + 'left': (coords.left - (alert.wrapper.getWidth() / 2)) + (this.getWidth() / 2), + 'top': coords.top - (alert.wrapper.getHeight()), + 'position': 'absolute' + }); + + } + +});
\ No newline at end of file diff --git a/module/webui/themes/flat/js/static/purr.min.js b/module/webui/themes/flat/js/static/purr.min.js new file mode 100644 index 000000000..bf70e357d --- /dev/null +++ b/module/webui/themes/flat/js/static/purr.min.js @@ -0,0 +1 @@ +var Purr=new Class({options:{mode:"top",position:"left",elementAlertClass:"purr-element-alert",elements:{wrapper:"div",alert:"div",buttonWrapper:"div",button:"button"},elementOptions:{wrapper:{styles:{position:"fixed","z-index":"9999"},"class":"purr-wrapper"},alert:{"class":"purr-alert",styles:{opacity:".85"}},buttonWrapper:{"class":"purr-button-wrapper"},button:{"class":"purr-button"}},alert:{buttons:[],clickDismiss:!0,hoverWait:!0,hideAfter:5e3,fx:{duration:500},highlight:!1,highlightRepeat:!1,highlight:{start:"#FF0",end:!1}}},Implements:[Options,Events,Chain],initialize:function(t){return this.setOptions(t),this.createWrapper(),this},bindAlert:function(){return this.alert.bind(this)},createWrapper:function(){this.wrapper=new Element(this.options.elements.wrapper,this.options.elementOptions.wrapper),"top"==this.options.mode?this.wrapper.setStyle("top",0):this.wrapper.setStyle("bottom",0),document.id(document.body).grab(this.wrapper),this.positionWrapper(this.options.position)},positionWrapper:function(t){if("object"==typeOf(t)){var e=this.getWrapperCoords();this.wrapper.setStyles({bottom:"",left:t.x,top:t.y-e.height,position:"absolute"})}else"left"==t?this.wrapper.setStyle("left",0):"right"==t?this.wrapper.setStyle("right",0):this.wrapper.setStyle("left",window.innerWidth/2-this.getWrapperCoords().width/2);return this},getWrapperCoords:function(){this.wrapper.setStyle("visibility","hidden");var t=this.alert("need something in here to measure"),e=this.wrapper.getCoordinates();return t.destroy(),this.wrapper.setStyle("visibility",""),e},alert:function(t,e){e=Object.merge({},this.options.alert,e||{});var i=new Element(this.options.elements.alert,this.options.elementOptions.alert);if("string"==typeOf(t))i.set("html",t);else if("element"==typeOf(t))i.grab(t);else if("array"==typeOf(t)){var s=[];return t.each(function(t){s.push(this.alert(t,e))},this),s}if(i.store("options",e),e.buttons.length>0){e.clickDismiss=!1,e.hideAfter=!1,e.hoverWait=!1;var r=new Element(this.options.elements.buttonWrapper,this.options.elementOptions.buttonWrapper);i.grab(r),e.buttons.each(function(t){if(void 0!=t.text){var e=new Element(this.options.elements.button,this.options.elementOptions.button);e.set("html",t.text),void 0!=t.callback&&e.addEvent("click",t.callback.pass(i)),void 0!=t.dismiss&&t.dismiss&&e.addEvent("click",this.dismiss.pass(i,this)),r.grab(e)}},this)}void 0!=e.className&&i.addClass(e.className),this.wrapper.grab(i,"top"==this.options.mode?"bottom":"top");var o=Object.merge(this.options.alert.fx,e.fx),n=new Fx.Morph(i,o);return i.store("fx",n),this.fadeIn(i),e.highlight&&n.addEvent("complete",function(){i.highlight(e.highlight.start,e.highlight.end),e.highlightRepeat&&i.highlight.periodical(e.highlightRepeat,i,[e.highlight.start,e.highlight.end])}),e.hideAfter&&this.dismiss(i),e.clickDismiss&&i.addEvent("click",function(){this.holdUp=!1,this.dismiss(i,!0)}.bind(this)),e.hoverWait&&i.addEvents({mouseenter:function(){this.holdUp=!0}.bind(this),mouseleave:function(){this.holdUp=!1}.bind(this)}),i},fadeIn:function(t){var e=t.retrieve("fx");e.set({opacity:0}),e.start({opacity:[this.options.elementOptions.alert.styles.opacity,.9].pick()})},dismiss:function(t,e){e=e||!1;var i=t.retrieve("options");e?this.fadeOut(t):this.fadeOut.delay(i.hideAfter,this,t)},fadeOut:function(t){if(this.holdUp)return this.dismiss.delay(100,this,[t,!0]),null;var e=t.retrieve("fx");if(!e)return null;var i={opacity:0};"top"==this.options.mode?i["margin-top"]="-"+t.offsetHeight+"px":i["margin-bottom"]="-"+t.offsetHeight+"px",e.start(i),e.addEvent("complete",function(){t.destroy()})}});Element.implement({alert:function(t,e){var i=this.retrieve("alert");i||(e=e||{mode:"top"},i=new Purr(e),this.store("alert",i));var s=this.getCoordinates();i.alert(t,e),i.wrapper.setStyles({bottom:"",left:s.left-i.wrapper.getWidth()/2+this.getWidth()/2,top:s.top-i.wrapper.getHeight(),position:"absolute"})}});
\ No newline at end of file diff --git a/module/webui/themes/flat/js/static/tinytab.js b/module/webui/themes/flat/js/static/tinytab.js new file mode 100644 index 000000000..de50279fc --- /dev/null +++ b/module/webui/themes/flat/js/static/tinytab.js @@ -0,0 +1,43 @@ +/* +--- +description: TinyTab - Tiny and simple tab handler for Mootools. + +license: MIT-style + +authors: +- Danillo César de O. Melo + +requires: +- core/1.2.4: '*' + +provides: TinyTab + +... +*/ +(function($) { + this.TinyTab = new Class({ + Implements: Events, + initialize: function(tabs, contents, opt) { + this.tabs = tabs; + this.contents = contents; + if(!opt) opt = {}; + this.css = opt.selectedClass || 'selected'; + this.select(this.tabs[0]); + tabs.each(function(el){ + el.addEvent('click',function(e){ + this.select(el); + e.stop(); + }.bind(this)); + }.bind(this)); + }, + + select: function(el) { + this.tabs.removeClass(this.css); + el.addClass(this.css); + this.contents.setStyle('display','none'); + var content = this.contents[this.tabs.indexOf(el)]; + content.setStyle('display','block'); + this.fireEvent('change',[content,el]); + } + }); +})(document.id);
\ No newline at end of file diff --git a/module/webui/themes/flat/js/static/tinytab.min.js b/module/webui/themes/flat/js/static/tinytab.min.js new file mode 100644 index 000000000..2f4fa0436 --- /dev/null +++ b/module/webui/themes/flat/js/static/tinytab.min.js @@ -0,0 +1 @@ +!function(){this.TinyTab=new Class({Implements:Events,initialize:function(s,t,e){this.tabs=s,this.contents=t,e||(e={}),this.css=e.selectedClass||"selected",this.select(this.tabs[0]),s.each(function(s){s.addEvent("click",function(t){this.select(s),t.stop()}.bind(this))}.bind(this))},select:function(s){this.tabs.removeClass(this.css),s.addClass(this.css),this.contents.setStyle("display","none");var t=this.contents[this.tabs.indexOf(s)];t.setStyle("display","block"),this.fireEvent("change",[t,s])}})}(document.id);
\ No newline at end of file diff --git a/module/webui/themes/flat/tml/admin.html b/module/webui/themes/flat/tml/admin.html new file mode 100644 index 000000000..c7bdd7894 --- /dev/null +++ b/module/webui/themes/flat/tml/admin.html @@ -0,0 +1,98 @@ +{% extends '/flat/tml/base.html' %} + +{% block head %} + <script type="text/javascript" src="/flat/js/render/admin.min.js"></script> +{% endblock %} + + +{% block title %}{{ _("Administrate") }} - {{ super() }} {% endblock %} +{% block subtitle %}{{ _("Administrate") }}{% endblock %} + +{% block content %} + + <a href="#" id="quit-pyload" style="font-size: large; font-weight: bold;">{{_("Quit pyLoad")}}</a> | + <a href="#" id="restart-pyload" style="font-size: large; font-weight: bold;">{{_("Restart pyLoad")}}</a> + <br> + <br> + + {{ _("To add user or change passwords use:") }} <b>python pyload.py -u</b><br> + {{ _("Important: Admin user have always all permissions!") }} + + <form action="" method="POST"> + <table class="settable wide"> + <thead style="font-size: 11px"> + <th> + {{ _("Name") }} + </th> + <th> + {{ _("Change Password") }} + </th> + <th> + {{ _("Admin") }} + </th> + <th> + {{ _("Permissions") }} + </th> + </thead> + + {% for name, data in users.iteritems() %} + <tr> + <td>{{ name }}</td> + <td><a class="change_password" href="#" id="change_pw|{{name}}">{{ _("change") }}</a></td> + <td><input name="{{ name }}|admin" type="checkbox" {% if data.perms.admin %} + checked="True" {% endif %}"></td> + <td> + <select multiple="multiple" size="{{ permlist|length }}" name="{{ name }}|perms"> + {% for perm in permlist %} + {% if data.perms|getitem(perm) %} + <option selected="selected">{{ perm }}</option> + {% else %} + <option>{{ perm }}</option> + {% endif %} + {% endfor %} + </select> + </td> + </tr> + {% endfor %} + + + </table> + + <button class="styled_button" type="submit">{{ _("Submit") }}</button> + </form> +{% endblock %} +{% block hidden %} + <div id="password_box" class="window_box" style="z-index: 2"> + <form id="password_form" action="/json/change_password" method="POST" enctype="multipart/form-data"> + <h1>{{ _("Change Password") }}</h1> + + <p>{{ _("Enter your current and desired Password.") }}</p> + <label for="user_login">{{ _("User") }} + <span class="small">{{ _("Your username.") }}</span> + </label> + <input id="user_login" name="user_login" type="text" size="20"/> + + <label for="login_current_password">{{ _("Current password") }} + <span class="small">{{ _("The password for this account.") }}</span> + </label> + <input id="login_current_password" name="login_current_password" type="password" size="20"/> + + <label for="login_new_password">{{ _("New password") }} + <span class="small">{{ _("The new password.") }}</span> + </label> + <input id="login_new_password" name="login_new_password" type="password" size="20"/> + + <label for="login_new_password2">{{ _("New password (repeat)") }} + <span class="small">{{ _("Please repeat the new password.") }}</span> + </label> + <input id="login_new_password2" name="login_new_password2" type="password" size="20"/> + + + <button id="login_password_button" type="submit">{{ _("Submit") }}</button> + <button id="login_password_reset" style="margin-left: 0" type="reset">{{ _("Reset") }}</button> + <div class="spacer"></div> + + </form> + + </div> +{% endblock %} diff --git a/module/webui/themes/flat/tml/base.html b/module/webui/themes/flat/tml/base.html new file mode 100644 index 000000000..17349c5f1 --- /dev/null +++ b/module/webui/themes/flat/tml/base.html @@ -0,0 +1,177 @@ +<?xml version="1.0" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<link rel="stylesheet" type="text/css" href="/flat/css/flat.min.css"/> +<link rel="stylesheet" type="text/css" href="/flat/css/window.min.css"/> +<link rel="stylesheet" type="text/css" href="/flat/css/MooDialog.min.css"/> + +<script type="text/javascript" src="/flat/js/static/mootools-core.min.js"></script> +<script type="text/javascript" src="/flat/js/static/mootools-more.min.js"></script> +<script type="text/javascript" src="/flat/js/static/MooDialog.min.js"></script> +<script type="text/javascript" src="/flat/js/static/purr.min.js"></script> + + +<script type="text/javascript" src="/flat/js/render/base.min.js"></script> + +<title>{% block title %}pyLoad {{_("Webinterface")}}{% endblock %}</title> + +{% block head %} +{% endblock %} +</head> +<body> +<a class="anchor" name="top" id="top"></a> + +<div id="head-panel"> + + + <div id="head-search-and-login"> + {% block headpanel %} + + {% if user.is_authenticated %} + + +{% if update %} +<span> +<span style="font-weight: 300; margin: 0 2px 0 2px;">{{_("pyLoad Update available!")}}</span> +</span> +{% endif %} + + +{% if plugins %} +<span> +<span style="font-weight: 300; margin: 0 2px 0 2px;">{{_("Plugins updated, please restart!")}}</span> +</span> +{% endif %} + +<span id="cap_info" style="display: {% if captcha %}inline{%else%}none{% endif %}"> +<img src="/flat/img/default/images.png" alt="Captcha:" style="vertical-align:middle; margin:2px" /> +<span style="font-weight: 300; cursor: pointer; margin-right: 2px;">{{_("Captcha waiting")}}</span> +</span> + + <img src="/flat/img/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user.name}}</span> + <ul id="user-actions"> + <li><a href="/logout" class="action logout" rel="nofollow">{{_("Logout")}}</a></li> + {% if user.is_admin %} + <li><a href="/admin" class="action profile" rel="nofollow">{{_("Administrate")}}</a></li> + {% endif %} + <li><a href="/info" class="action info" rel="nofollow">{{_("Info")}}</a></li> + + </ul> +{% else %} + <span style="padding-right: 2px;">{{_("Please Login!")}}</span> +{% endif %} + + {% endblock %} + </div> + + <a href="/"><img id="head-logo" src="/flat/img/default/pyload-logo.png" alt="pyLoad" /></a> + + <div id="head-menu"> + <ul> + + {% macro selected(name, right=False) -%} + {% if name in url -%}class="{% if right -%}right {% endif %}selected"{%- endif %} + {% if not name in url and right -%}class="right"{%- endif %} + {%- endmacro %} + + + {% block menu %} + <li> + <a href="/" title=""><img src="/flat/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> + </li> + <li {{ selected('queue') }}> + <a href="/queue/" title=""><img src="/flat/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> + </li> + <li {{ selected('collector') }}> + <a href="/collector/" title=""><img src="/flat/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> + </li> + <li {{ selected('downloads') }}> + <a href="/downloads/" title=""><img src="/flat/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> + </li> + <li {{ selected('logs', True) }}> + <a href="/logs/" title=""><img src="/flat/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> + </li> + <li {{ selected('settings', True) }}> + <a href="/settings/" title=""><img src="/flat/img/head-menu-config.png" alt="" />{{_("Config")}}</a> + </li> + {% endblock %} + + </ul> + </div> + + <div style="clear:both;"></div> +</div> + +{% if perms.STATUS %} +<ul id="page-actions2"> + <li id="action_play"><a href="#" class="action play" accesskey="o" rel="nofollow">{{_("Start")}}</a></li> + <li id="action_stop"><a href="#" class="action stop" accesskey="o" rel="nofollow">{{_("Stop")}}</a></li> + <li id="action_cancel"><a href="#" class="action cancel" accesskey="o" rel="nofollow">{{_("Cancel")}}</a></li> + <li id="action_add"><a href="#" class="action add" accesskey="o" rel="nofollow" >{{_("Add")}}</a></li> +</ul> +{% endif %} + +{% if perms.LIST %} +<ul id="page-actions"> + <li><span class="time">{{_("Download:")}}</span><a id="time" style=" background-color: {% if status.download %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm; "> {% if status.download %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li> + <li><span class="reconnect">{{_("Reconnect:")}}</span><a id="reconnect" style=" background-color: {% if status.reconnect %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm;color:black; "> {% if status.reconnect %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li> + <li><a class="action backlink">{{_("Speed:")}} <b id="speed">{{ status.speed }}</b></a></li> + <li><a class="action cog">{{_("Active:")}} <b id="aktiv" title="{{_("Active")}}">{{ status.active }}</b> / <b id="aktiv_from" title="{{_("Queued")}}">{{ status.queue }}</b> / <b id="aktiv_total" title="{{_("Total")}}">{{ status.total }}</b></a></li> + <li><a href="" class="action revisions" accesskey="o" rel="nofollow">{{_("Reload page")}}</a></li> +</ul> +{% endif %} + +{% block pageactions %} +{% endblock %} +<br/> + +<div id="body-wrapper" class="dokuwiki"> + +<div id="content" lang="en" dir="ltr"> + +<h1>{% block subtitle %}pyLoad - {{_("Webinterface")}}{% endblock %}</h1> + +{% block statusbar %} +{% endblock %} + + +<br/> + +<div class="level1" style="clear:both"> +</div> +<noscript><h1>Enable JavaScript to use the webinterface.</h1></noscript> + +{% for message in messages %} + <b><p>{{message}}</p></b> +{% endfor %} + +<div id="load-indicator" style="opacity: 0; float: right; margin-top: -10px;"> + <img src="/flat/img/default/ajax-loader.gif" alt="" style="padding-right: 5px"/> + {{_("loading")}} +</div> + +{% block content %} +{% endblock content %} + + <hr style="clear: both;" /> + +<div id="foot">© 2008-2014 pyLoad Team +<a href="#top" class="action top" accesskey="x"><span>{{_("Back to top")}}</span></a><br /> +<!--<div class="breadcrumbs"></div>--> + +</div> +</div> +</div> + +<div style="display: none;"> + {% include '/flat/tml/window.html' %} + {% include '/flat/tml/captcha.html' %} + {% block hidden %} + {% endblock %} +</div> +</body> +</html> diff --git a/module/webui/themes/flat/tml/captcha.html b/module/webui/themes/flat/tml/captcha.html new file mode 100644 index 000000000..ae1afe444 --- /dev/null +++ b/module/webui/themes/flat/tml/captcha.html @@ -0,0 +1,42 @@ +<!-- Captcha box --> +<div id="cap_box" class="window_box"> + + <form id="cap_form" action="/json/set_captcha" method="POST" enctype="multipart/form-data" onsubmit="return false;"> + + <h1>{{_("Captcha reading")}}</h1> + <p id="cap_title">{{_("Please read the text on the captcha.")}}</p> + + <div id="cap_textual"> + + <input id="cap_id" name="cap_id" type="hidden" value="" /> + + <label>{{_("Captcha")}} + <span class="small">{{_("The captcha.")}}</span> + </label> + <span class="cont"> + <img id="cap_textual_img" src=""> + </span> + + <label>{{_("Text")}} + <span class="small">{{_("Input the text on the captcha.")}}</span> + </label> + <input id="cap_result" name="cap_result" type="text" size="20" /> + + </div> + + <div id="cap_positional" style="text-align: center"> + <img id="cap_positional_img" src="" style="margin: 10px; cursor:pointer"> + </div> + + <div id="button_bar" style="text-align: center"> + <span> + <button id="cap_submit" type="submit" style="margin-left: 0">{{_("Submit")}}</button> + <button id="cap_reset" type="reset" style="margin-left: 0">{{_("Close")}}</button> + </span> + </div> + + <div class="spacer"></div> + + </form> + +</div>
\ No newline at end of file diff --git a/module/webui/themes/flat/tml/downloads.html b/module/webui/themes/flat/tml/downloads.html new file mode 100644 index 000000000..445f8da37 --- /dev/null +++ b/module/webui/themes/flat/tml/downloads.html @@ -0,0 +1,29 @@ +{% extends '/flat/tml/base.html' %} + +{% block title %}Downloads - {{super()}} {% endblock %} + +{% block subtitle %} +{{_("Downloads")}} +{% endblock %} + +{% block content %} + +<ul> + {% for folder in files.folder %} + <li> + {{ folder.name }} + <ul> + {% for file in folder.files %} + <li><a href='get/{{ folder.path|escape }}/{{ file|escape }}'>{{file}}</a></li> + {% endfor %} + </ul> + </li> + {% endfor %} + + {% for file in files.files %} + <li> <a href='get/{{ file|escape }}'>{{ file }}</a></li> + {% endfor %} + +</ul> + +{% endblock %}
\ No newline at end of file diff --git a/module/webui/themes/flat/tml/folder.html b/module/webui/themes/flat/tml/folder.html new file mode 100644 index 000000000..89b84e7bb --- /dev/null +++ b/module/webui/themes/flat/tml/folder.html @@ -0,0 +1,15 @@ +<li class="folder"> + <input type="hidden" name="path" class="path" value="{{ path }}" /> + <input type="hidden" name="name" class="name" value="{{ name }}" /> + <span> + <b>{{ name }}</b> + <span class="buttons" style="opacity:0"> + <img title="{{_("Rename Directory")}}" class="rename" style="cursor: pointer" height="12px" src="/flat/img/pencil.png" /> + + <img title="{{_("Delete Directory")}}" class="delete" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/flat/img/delete.png" /> + + <img title="{{_("Add subdirectory")}}" class="mkdir" style="margin-left: -10px; cursor: pointer" width="12px" height="12px" src="/flat/img/default/add_folder.png" /> + </span> + </span> + <div style="display:none">{{ _("Folder is empty") }}</div> +</li>
\ No newline at end of file diff --git a/module/webui/themes/flat/tml/home.html b/module/webui/themes/flat/tml/home.html new file mode 100644 index 000000000..838a351ad --- /dev/null +++ b/module/webui/themes/flat/tml/home.html @@ -0,0 +1,263 @@ +{% extends '/flat/tml/base.html' %} +{% block head %} + +<script type="text/javascript"> + +var em; +var operafix = (navigator.userAgent.toLowerCase().search("opera") >= 0); + +document.addEvent("domready", function(){ + em = new EntryManager(); +}); + +var EntryManager = new Class({ + initialize: function(){ + this.json = new Request.JSON({ + url: "json/links", + secure: false, + async: true, + onSuccess: this.update.bind(this), + initialDelay: 0, + delay: 2500, + limit: 30000 + }); + + this.ids = [{% for link in content %} + {% if forloop.last %} + {{ link.id }} + {% else %} + {{ link.id }}, + {% endif %} + {% endfor %}]; + + this.entries = []; + this.container = $('LinksAktiv'); + + this.parseFromContent(); + + this.json.startTimer(); + }, + parseFromContent: function(){ + this.ids.each(function(id,index){ + var entry = new LinkEntry(id); + entry.parse(); + this.entries.push(entry) + }, this); + }, + update: function(data){ + + try{ + this.ids = this.entries.map(function(item){ + return item.fid + }); + + this.ids.filter(function(id){ + return !this.ids.contains(id) + },data).each(function(id){ + var index = this.ids.indexOf(id); + this.entries[index].remove(); + this.entries = this.entries.filter(function(item){return item.fid != this},id); + this.ids = this.ids.erase(id) + }, this); + + data.links.each(function(link, i){ + if (this.ids.contains(link.fid)){ + + var index = this.ids.indexOf(link.fid); + this.entries[index].update(link) + + }else{ + var entry = new LinkEntry(link.fid); + entry.insert(link); + this.entries.push(entry); + this.ids.push(link.fid); + this.container.adopt(entry.elements.tr,entry.elements.pgbTr); + entry.fade.start('opacity', 1); + entry.fadeBar.start('opacity', 1); + + } + }, this) + }catch(e){ + //alert(e) + } + } +}); + + +var LinkEntry = new Class({ + initialize: function(id){ + this.fid = id; + this.id = id; + }, + parse: function(){ + this.elements = { + tr: $("link_{id}".substitute({id: this.id})), + name: $("link_{id}_name".substitute({id: this.id})), + status: $("link_{id}_status".substitute({id: this.id})), + info: $("link_{id}_info".substitute({id: this.id})), + bleft: $("link_{id}_bleft".substitute({id: this.id})), + percent: $("link_{id}_percent".substitute({id: this.id})), + remove: $("link_{id}_remove".substitute({id: this.id})), + pgbTr: $("link_{id}_pgb_tr".substitute({id: this.id})), + pgb: $("link_{id}_pgb".substitute({id: this.id})) + }; + this.initEffects(); + }, + insert: function(item){ + try{ + + this.elements = { + tr: new Element('tr', { + 'html': '', + 'styles':{ + 'opacity': 0 + } + }), + name: new Element('td', { + 'html': item.name + }), + status: new Element('td', { + 'html': item.statusmsg + }), + info: new Element('td', { + 'html': item.info + }), + bleft: new Element('td', { + 'html': humanFileSize(item.size) + }), + percent: new Element('span', { + 'html': item.percent+ '% / '+ humanFileSize(item.size-item.bleft) + }), + remove: new Element('img',{ + 'src': '/flat/img/control_cancel.png', + 'styles':{ + 'vertical-align': 'middle', + 'margin-right': '-20px', + 'margin-left': '5px', + 'margin-top': '-2px', + 'cursor': 'pointer' + } + }), + pgbTr: new Element('tr', { + 'html':'' + }), + pgb: new Element('div', { + 'html': ' ', + 'styles':{ + 'height': '4px', + 'width': item.percent+'%', + 'background-color': '#ddd' + } + }) + }; + + this.elements.tr.adopt(this.elements.name,this.elements.status,this.elements.info,this.elements.bleft,new Element('td').adopt(this.elements.percent,this.elements.remove)); + this.elements.pgbTr.adopt(new Element('td',{'colspan':5}).adopt(this.elements.pgb)); + this.initEffects(); + }catch(e){ + alert(e) + } + }, + initEffects: function(){ + if(!operafix) + this.bar = new Fx.Morph(this.elements.pgb, {unit: '%', duration: 5000, link: 'link', fps:30}); + this.fade = new Fx.Tween(this.elements.tr); + this.fadeBar = new Fx.Tween(this.elements.pgbTr); + + this.elements.remove.addEvent('click', function(){ + new Request({method: 'get', url: '/json/abort_link/'+this.id}).send(); + }.bind(this)); + + }, + update: function(item){ + this.elements.name.set('text', item.name); + this.elements.status.set('text', item.statusmsg); + this.elements.info.set('text', item.info); + this.elements.bleft.set('text', item.format_size); + this.elements.percent.set('text', item.percent+ '% / '+ humanFileSize(item.size-item.bleft)); + if(!operafix) + { + this.bar.start({ + 'width': item.percent, + 'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex() + }); + } + else + { + this.elements.pgb.set( + 'styles', { + 'height': '4px', + 'width': item.percent+'%', + 'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex(), + }); + } + }, + remove: function(){ + this.fade.start('opacity',0).chain(function(){this.elements.tr.dispose();}.bind(this)); + this.fadeBar.start('opacity',0).chain(function(){this.elements.pgbTr.dispose();}.bind(this)); + + } + }); +</script> + +{% endblock %} + +{% block subtitle %} +{{_("Active Downloads")}} +{% endblock %} + +{% block menu %} +<li class="selected"> + <a href="/" title=""><img src="/flat/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> +</li> +<li> + <a href="/queue/" title=""><img src="/flat/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> +</li> +<li> + <a href="/collector/" title=""><img src="/flat/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> +</li> +<li> + <a href="/downloads/" title=""><img src="/flat/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> +</li> +<li class="right"> + <a href="/logs/" title=""><img src="/flat/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> +</li> +<li class="right"> + <a href="/settings/" title=""><img src="/flat/img/head-menu-config.png" alt="" />{{_("Config")}}</a> +</li> +{% endblock %} + +{% block content %} +<table width="100%" class="queue"> + <thead> + <tr class="header"> + <th>{{_("Name")}}</th> + <th>{{_("Status")}}</th> + <th>{{_("Information")}}</th> + <th>{{_("Size")}}</th> + <th>{{_("Progress")}}</th> + </tr> + </thead> + <tbody id="LinksAktiv"> + + {% for link in content %} + <tr id="link_{{ link.id }}"> + <td id="link_{{ link.id }}_name">{{ link.name }}</td> + <td id="link_{{ link.id }}_status">{{ link.status }}</td> + <td id="link_{{ link.id }}_info">{{ link.info }}</td> + <td id="link_{{ link.id }}_bleft">{{ link.format_size }}</td> + <td> + <span id="link_{{ link.id }}_percent">{{ link.percent }}% /{{ link.bleft }}</span> + <img id="link_{{ link.id }}_remove" style="vertical-align: middle; margin-right: -20px; margin-left: 5px; margin-top: -2px; cursor:pointer;" src="/flat/img/control_cancel.png"/> + </td> + </tr> + <tr id="link_{{ link.id }}_pgb_tr"> + <td colspan="5"> + <div id="link_{{ link.id }}_pgb" class="progressBar" style="background-color: green; height:4px; width: {{ link.percent }}%;"> </div> + </td> + </tr> + {% endfor %} + + </tbody> +</table> +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/info.html b/module/webui/themes/flat/tml/info.html index 77ae57376..26b46736d 100644 --- a/module/web/templates/default/info.html +++ b/module/webui/themes/flat/tml/info.html @@ -1,10 +1,10 @@ -{% extends 'default/base.html' %} +{% extends '/flat/tml/base.html' %} {% block head %} <script type="text/javascript"> window.addEvent("domready", function() { var ul = new Element('ul#twitter_update_list'); - var script1 = new Element('script[src=http://twitter.com/javascripts/blogger.js][type=text/javascript]'); + var script1 = new Element('script[src=http://twitter.com/javascripts/blogger.min.js][type=text/javascript]'); var script2 = new Element('script[src=http://twitter.com/statuses/user_timeline/pyLoad.json?callback=twitterCallback2&count=6][type=text/javascript]'); $("twitter").adopt(ul, script1, script2); }); diff --git a/module/webui/themes/flat/tml/login.html b/module/webui/themes/flat/tml/login.html new file mode 100644 index 000000000..76365a79c --- /dev/null +++ b/module/webui/themes/flat/tml/login.html @@ -0,0 +1,36 @@ +{% extends '/flat/tml/base.html' %} + +{% block title %}{{_("Login")}} - {{super()}} {% endblock %} + +{% block content %} + +<div class="centeralign"> +<form action="" method="post" accept-charset="utf-8" id="login"> + <div class="no"> + <input type="hidden" name="do" value="login" /> + <fieldset> + <legend>Login</legend> + <label> + <span>{{_("Username")}}</span> + <input type="text" size="20" name="username" /> + </label> + <br /> + <label> + <span>{{_("Password")}}</span> + <input type="password" size="20" name="password" /> + </label> + <br /> + <input type="submit" value="Login" class="button" /> + </fieldset> + </div> +</form> + +{% if errors %} +<p>{{_("Your username and password didn't match. Please try again.")}}</p> + {{ _("To reset your login data or add an user run:") }} <b> python pyload.py -u</b> +{% endif %} + +</div> +<br> + +{% endblock %} diff --git a/module/webui/themes/flat/tml/logout.html b/module/webui/themes/flat/tml/logout.html new file mode 100644 index 000000000..370031b25 --- /dev/null +++ b/module/webui/themes/flat/tml/logout.html @@ -0,0 +1,9 @@ +{% extends '/flat/tml/base.html' %} + +{% block head %} +<meta http-equiv="refresh" content="3; url=/"> +{% endblock %} + +{% block content %} +<p><b>{{_("You were successfully logged out.")}}</b></p> +{% endblock %}
\ No newline at end of file diff --git a/module/webui/themes/flat/tml/logs.html b/module/webui/themes/flat/tml/logs.html new file mode 100644 index 000000000..87e5a0f30 --- /dev/null +++ b/module/webui/themes/flat/tml/logs.html @@ -0,0 +1,41 @@ +{% extends '/flat/tml/base.html' %} + +{% block title %}{{_("Logs")}} - {{super()}} {% endblock %} +{% block subtitle %}{{_("Logs")}}{% endblock %} +{% block head %} +<link rel="stylesheet" type="text/css" href="/flat/css/log.min.css"/> +{% endblock %} + +{% block content %} +<div style="clear: both;"></div> + +<div class="logpaginator"><a href="{{ "/logs/1" }}"><< {{_("Start")}}</a> <a href="{{ "/logs/" + iprev|string }}">< {{_("prev")}}</a> <a href="{{ "/logs/" + inext|string }}">{{_("next")}} ></a> <a href="/logs/">{{_("End")}} >></a></div> +<div class="logperpage"> + <form id="logform1" action="" method="POST"> + <label for="reversed">Reversed:</label> + <input type="checkbox" name="reversed" onchange="this.form.submit();" {% if reversed %} checked="checked" {% endif %} /> + <label for="perpage">Lines per page:</label> + <select name="perpage" onchange="this.form.submit();"> + {% for value in perpage_p %} + <option value="{{value.0}}"{% if value.0 == perpage %} selected="selected" {% endif %}>{{value.1}}</option> + {% endfor %} + </select> + </form> +</div> +<div class="logwarn">{{warning}}</div> +<div style="clear: both;"></div> +<div class="logdiv"> + <table class="logtable" cellpadding="0" cellspacing="0"> + {% for line in log %} + <tr><td class="logline">{{line.line}}</td><td>{{line.date}}</td><td class="loglevel">{{line.level}}</td><td>{{line.message}}</td></tr> + {% endfor %} + </table> +</div> +<div class="logform"> +<form id="logform2" action="" method="POST"> + <label for="from">Jump to time:</label><input type="text" name="from" size="15" value="{{from}}"/> + <input type="submit" value="ok" /> +</form> +</div> +<div style="clear: both; height: 10px;"> </div> +{% endblock %}
\ No newline at end of file diff --git a/module/webui/themes/flat/tml/pathchooser.html b/module/webui/themes/flat/tml/pathchooser.html new file mode 100644 index 000000000..95a1a3be5 --- /dev/null +++ b/module/webui/themes/flat/tml/pathchooser.html @@ -0,0 +1,76 @@ +<html> +<head> + <script class="javascript"> + function chosen() + { + opener.ifield.value = document.forms[0].p.value; + close(); + } + function exit() + { + close(); + } + function setInvalid() { + document.forms[0].send.disabled = 'disabled'; + document.forms[0].p.style.color = '#FF0000'; + } + function setValid() { + document.forms[0].send.disabled = ''; + document.forms[0].p.style.color = '#000000'; + } + function setFile(file) + { + document.forms[0].p.value = file; + setValid(); + + } + </script> + <link rel="stylesheet" type="text/css" href="/flat/css/pathchooser.min.css"/> +</head> +<body{% if type == 'file' %}{% if not oldfile %} onload="setInvalid();"{% endif %}{% endif %}> +<center> + <div id="paths"> + <form method="get" action="?" onSubmit="chosen();" onReset="exit();"> + <input type="text" name="p" value="{{ oldfile|default(cwd) }}" size="60" onfocus="setValid();"> + <input type="submit" value="Ok" name="send"> + </form> + + {% if type == 'folder' %} + <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/pathchooser" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/pathchooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> + {% else %} + <span class="path_abs_rel">{{_("Path")}}: <a href="{{ "/filechooser/" + cwd|path_make_absolute|quotepath }}"{% if absolute %} style="text-decoration: underline;"{% endif %}>{{_("absolute")}}</a> | <a href="{{ "/filechooser/" + cwd|path_make_relative|quotepath }}"{% if not absolute %} style="text-decoration: underline;"{% endif %}>{{_("relative")}}</a></span> + {% endif %} + </div> + <table border="0" cellspacing="0" cellpadding="3"> + <tr> + <th>{{_("name")}}</th> + <th>{{_("size")}}</th> + <th>{{_("type")}}</th> + <th>{{_("last modified")}}</th> + </tr> + {% if parentdir %} + <tr> + <td colspan="4"> + <a href="{% if type == 'folder' %}{{ "/pathchooser/" + parentdir|quotepath }}{% else %}{{ "/filechooser/" + parentdir|quotepath }}{% endif %}"><span class="parentdir">{{_("parent directory")}}</span></a> + </td> + </tr> + {% endif %} +{% for file in files %} + <tr> + {% if type == 'folder' %} + <td class="name">{% if file.type == 'dir' %}<a href="{{ "/pathchooser/" + file.fullpath|quotepath }}" title="{{ file.fullpath }}"><span class="path_directory">{{ file.name|truncate(25) }}</span></a>{% else %}<span class="path_file" title="{{ file.fullpath }}">{{ file.name|truncate(25) }}{% endif %}</span></td> + {% else %} + <td class="name">{% if file.type == 'dir' %}<a href="{{ "/filechooser/" + file.fullpath|quotepath }}" title="{{ file.fullpath }}"><span class="file_directory">{{ file.name|truncate(25) }}</span></a>{% else %}<a href="#" onclick="setFile('{{ file.fullpath }}');" title="{{ file.fullpath }}"><span class="file_file">{{ file.name|truncate(25) }}{% endif %}</span></a></td> + {% endif %} + <td class="size">{{ file.size|float|filesizeformat }}</td> + <td class="type">{% if file.type == 'dir' %}directory{% else %}{{ file.ext|default("file") }}{% endif %}</td> + <td class="mtime">{{ file.modified|date("d.m.Y - H:i:s") }}</td> + <tr> +<!-- <tr> + <td colspan="4">{{_("no content")}}</td> + </tr> --> +{% endfor %} + </table> + </center> +</body> +</html>
\ No newline at end of file diff --git a/module/webui/themes/flat/tml/queue.html b/module/webui/themes/flat/tml/queue.html new file mode 100644 index 000000000..0d3022ddd --- /dev/null +++ b/module/webui/themes/flat/tml/queue.html @@ -0,0 +1,104 @@ +{% extends '/flat/tml/base.html' %} +{% block head %} + +<script type="text/javascript" src="/flat/js/render/package.min.js"></script> + +<script type="text/javascript"> + +document.addEvent("domready", function(){ + var pUI = new PackageUI("url", {{ target }}); +}); +</script> +{% endblock %} + +{% if target %} + {% set name = _("Queue") %} +{% else %} + {% set name = _("Collector") %} +{% endif %} + +{% block title %}{{name}} - {{super()}} {% endblock %} +{% block subtitle %}{{name}}{% endblock %} + +{% block pageactions %} +<ul id="page-actions-more"> + <li id="del_finished"><a style="padding: 0; font-weight: 300;" href="#">{{_("Delete Finished")}}</a></li> + <li id="restart_failed"><a style="padding: 0; font-weight: 300;" href="#">{{_("Restart Failed")}}</a></li> +</ul> +{% endblock %} + +{% block content %} +{% autoescape true %} + +<ul id="package-list" style="list-style: none; padding-left: 0; margin-top: -10px;"> +{% for package in content %} + <li> +<div id="package_{{package.pid}}" class="package"> + <div class="order" style="display: none;">{{ package.order }}</div> + + <div class="packagename" style="cursor: pointer"> + <img class="package_drag" src="/flat/img/folder.png" style="cursor: move; margin-bottom: -2px"> + <span class="name">{{package.name}}</span> + + <span class="buttons" style="opacity:0"> + <img title="{{_("Delete Package")}}" style="cursor: pointer" width="12px" height="12px" src="/flat/img/delete.png" /> + + <img title="{{_("Restart Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/flat/img/arrow_refresh.png" /> + + <img title="{{_("Edit Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/flat/img/pencil.png" /> + + <img title="{{_("Move Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/flat/img/package_go.png" /> + </span> + </div> + {% set progress = (package.linksdone * 100) / package.linkstotal %} + + <div id="progress" style="border-radius: 0px; border: 1px solid #AAAAAA; width: 50%; height: 1em"> + <div style="width: {{ progress }}%; height: 100%; background-color: #add8e6;"></div> + <label style="font-size: 0.8em; font-weight: 300; padding-left: 5px; position: relative; top: -17px"> + {{ package.sizedone|formatsize }} / {{ package.sizetotal|formatsize }}</label> + <label style="font-size: 0.8em; font-weight: 300; padding-right: 5px ;float: right; position: relative; top: -17px"> + {{ package.linksdone }} / {{ package.linkstotal }}</label> + </div> + <div style="clear: both; margin-bottom: -10px"></div> + + <div id="children_{{package.pid}}" style="display: none;" class="children"> + <span class="child_secrow">{{_("Folder:")}} <span class="folder">{{package.folder}}</span> | {{_("Password:")}} <span class="password">{{package.password}}</span></span> + <ul id="sort_children_{{package.pid}}" style="list-style: none; padding-left: 0"> + </ul> + </div> +</div> + </li> +{% endfor %} +</ul> +{% endautoescape %} +{% endblock %} + +{% block hidden %} +<div id="pack_box" class="window_box" style="z-index: 2"> + <form id="pack_form" action="/json/edit_package" method="POST" enctype="multipart/form-data"> + <h1>{{_("Edit Package")}}</h1> + <p>{{_("Edit the package detais below.")}}</p> + <input name="pack_id" id="pack_id" type="hidden" value=""/> + <label for="pack_name">{{_("Name")}} + <span class="small">{{_("The name of the package.")}}</span> + </label> + <input id="pack_name" name="pack_name" type="text" size="20" /> + + <label for="pack_folder">{{_("Folder")}} + <span class="small">{{_("Name of subfolder for these downloads.")}}</span> + </label> + <input id="pack_folder" name="pack_folder" type="text" size="20" /> + + <label for="pack_pws">{{_("Password")}} + <span class="small">{{_("List of passwords used for unrar.")}}</span> + </label> + <textarea rows="3" name="pack_pws" id="pack_pws"></textarea> + + <button type="submit">{{_("Submit")}}</button> + <button id="pack_reset" style="margin-left: 0" type="reset" >{{_("Reset")}}</button> + <div class="spacer"></div> + + </form> + +</div> +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/settings.html b/module/webui/themes/flat/tml/settings.html index a4443025a..1bd0d1e17 100644 --- a/module/web/templates/default/settings.html +++ b/module/webui/themes/flat/tml/settings.html @@ -1,12 +1,12 @@ -{% extends 'default/base.html' %} +{% extends '/flat/tml/base.html' %} {% block title %}{{ _("Config") }} - {{ super() }} {% endblock %} {% block subtitle %}{{ _("Config") }}{% endblock %} {% block head %} - <script type="text/javascript" src="/media/js/tinytab_static.js"></script> - <script type="text/javascript" src="/media/js/MooDropMenu_static.js"></script> - <script type="text/javascript" src="/media/js/settings.js"></script> + <script type="text/javascript" src="/flat/js/static/tinytab.min.js"></script> + <script type="text/javascript" src="/flat/js/static/MooDropMenu.min.js"></script> + <script type="text/javascript" src="/flat/js/render/settings.min.js"></script> {% endblock %} @@ -107,7 +107,7 @@ <td> <span style="padding:5px">{{ plugin }}</span> </td> - + <td><label for="{{plugin}}|password;{{account.login}}" style="color:#424242;">{{ account.login }}</label></td> <td> diff --git a/module/web/templates/default/settings_item.html b/module/webui/themes/flat/tml/settings_item.html index 813383343..813383343 100644 --- a/module/web/templates/default/settings_item.html +++ b/module/webui/themes/flat/tml/settings_item.html diff --git a/module/webui/themes/flat/tml/window.html b/module/webui/themes/flat/tml/window.html new file mode 100644 index 000000000..8f57843c6 --- /dev/null +++ b/module/webui/themes/flat/tml/window.html @@ -0,0 +1,46 @@ +<iframe id="upload_target" name="upload_target" src="" style="display: none; width:0;height:0"></iframe> + +<div id="add_box" class="window_box"> +<form id="add_form" action="/json/add_package" method="POST" enctype="multipart/form-data"> +<h1>{{_("Add Package")}}</h1> +<p>{{_("Paste your links or upload a container.")}}</p> +<label for="add_name">{{_("Name")}} +<span class="small">{{_("The name of the new package.")}}</span> +</label> +<input id="add_name" name="add_name" type="text" size="20" /> + +<label for="add_links">{{_("Links")}} +<span class="small">{{_("Paste your links here or any text and press the filter button.")}}</span> +<span class="small"> {{ _("Filter urls") }} +<img alt="URIParsing" Title="Parse Uri" src="/flat/img/default/parseUri.png" style="cursor:pointer; vertical-align: text-bottom;" onclick="parseUri()"/> +</span> + +</label> +<textarea rows="5" name="add_links" id="add_links"></textarea> + +<label for="add_password">{{_("Password")}} + <span class="small">{{_("Password for RAR-Archive")}}</span> +</label> +<input id="add_password" name="add_password" type="text" size="20"> + +<label>{{_("File")}} +<span class="small">{{_("Upload a container.")}}</span> +</label> +<input type="file" name="add_file" id="add_file"/> + +<label for="add_dest">{{_("Destination")}} +</label> +<span class="cont"> + {{_("Queue")}} + <input type="radio" name="add_dest" id="add_dest" value="1" checked="checked"/> + {{_("Collector")}} + <input type="radio" name="add_dest" id="add_dest2" value="0"/> +</span> + +<button type="submit">{{_("Add Package")}}</button> +<button id="add_reset" style="margin-left:0;" type="reset">{{_("Reset")}}</button> +<div class="spacer"></div> + +</form> + +</div>
\ No newline at end of file diff --git a/pyLoadGui.py b/pyLoadGui.py deleted file mode 100755 index 5f620e52a..000000000 --- a/pyLoadGui.py +++ /dev/null @@ -1,765 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -import sys - -from uuid import uuid4 as uuid # should be above PyQt imports -from time import sleep, time - -from base64 import b64decode - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -import re -import module.common.pylgettext as gettext -import os -from os.path import abspath -from os.path import join -from os.path import basename -from os.path import commonprefix - -from module import InitHomeDir -from module.gui.ConnectionManager import * -from module.gui.Connector import Connector -from module.gui.MainWindow import * -from module.gui.Queue import * -from module.gui.Overview import * -from module.gui.Collector import * -from module.gui.XMLParser import * -from module.gui.CoreConfigParser import ConfigParser - -from module.lib.rename_process import renameProcess -from module.utils import formatSize, formatSpeed - -try: - import pynotify -except ImportError: - print "pynotify not installed, falling back to qt tray notification" - -class main(QObject): - def __init__(self): - """ - main setup - """ - QObject.__init__(self) - self.app = QApplication(sys.argv) - self.path = pypath - self.homedir = abspath("") - - self.configdir = "" - - self.init(True) - - def init(self, first=False): - """ - set main things up - """ - self.parser = XMLParser(join(self.configdir, "gui.xml"), join(self.path, "module", "config", "gui_default.xml")) - lang = self.parser.xml.elementsByTagName("language").item(0).toElement().text() - if not lang: - parser = XMLParser(join(self.path, "module", "config", "gui_default.xml")) - lang = parser.xml.elementsByTagName("language").item(0).toElement().text() - - gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) - translation = gettext.translation("pyLoadGui", join(pypath, "locale"), languages=[str(lang), "en"], fallback=True) - try: - translation.install(unicode=(True if sys.stdout.encoding.lower().startswith("utf") else False)) - except: - translation.install(unicode=False) - - - self.connector = Connector() - self.mainWindow = MainWindow(self.connector) - self.connWindow = ConnectionManager() - self.mainloop = self.Loop(self) - self.connectSignals() - - self.checkClipboard = False - default = self.refreshConnections() - self.connData = None - self.captchaProcessing = False - self.serverStatus = {"freespace":0} - - self.core = None # pyLoadCore if started - self.connectionLost = False - - if True: # when used if first, minimizing not working correctly.. - self.tray = TrayIcon() - self.tray.show() - self.notification = Notification(self.tray) - self.connect(self, SIGNAL("showMessage"), self.notification.showMessage) - self.connect(self.tray.exitAction, SIGNAL("triggered()"), self.slotQuit) - self.connect(self.tray.showAction, SIGNAL("toggled(bool)"), self.mainWindow.setVisible) - self.connect(self.mainWindow, SIGNAL("hidden"), self.tray.mainWindowHidden) - - if not first: - self.connWindow.show() - else: - self.connWindow.edit.setData(default) - data = self.connWindow.edit.getData() - self.slotConnect(data) - - def startMain(self): - """ - start all refresh threads and show main window - """ - if not self.connector.connectProxy(): - self.init() - return - self.connect(self.connector, SIGNAL("connectionLost"), self.slotConnectionLost) - self.restoreMainWindow() - self.mainWindow.show() - self.initQueue() - self.initPackageCollector() - self.mainloop.start() - self.clipboard = self.app.clipboard() - self.connect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) - self.mainWindow.actions["clipboard"].setChecked(self.checkClipboard) - - self.mainWindow.tabs["settings"]["w"].setConnector(self.connector) - self.mainWindow.tabs["settings"]["w"].loadConfig() - self.tray.showAction.setDisabled(False) - - def stopMain(self): - """ - stop all refresh threads and hide main window - """ - self.tray.showAction.setDisabled(True) - self.disconnect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) - self.disconnect(self.connector, SIGNAL("connectionLost"), self.slotConnectionLost) - self.mainloop.stop() - self.mainWindow.saveWindow() - self.mainWindow.hide() - self.queue.stop() - - def connectSignals(self): - """ - signal and slot stuff, yay! - """ - self.connect(self.connector, SIGNAL("errorBox"), self.slotErrorBox) - self.connect(self.connWindow, SIGNAL("saveConnection"), self.slotSaveConnection) - self.connect(self.connWindow, SIGNAL("removeConnection"), self.slotRemoveConnection) - self.connect(self.connWindow, SIGNAL("connect"), self.slotConnect) - self.connect(self.mainWindow, SIGNAL("connector"), self.slotShowConnector) - self.connect(self.mainWindow, SIGNAL("addPackage"), self.slotAddPackage) - self.connect(self.mainWindow, SIGNAL("setDownloadStatus"), self.slotSetDownloadStatus) - self.connect(self.mainWindow, SIGNAL("saveMainWindow"), self.slotSaveMainWindow) - self.connect(self.mainWindow, SIGNAL("pushPackageToQueue"), self.slotPushPackageToQueue) - self.connect(self.mainWindow, SIGNAL("restartDownload"), self.slotRestartDownload) - self.connect(self.mainWindow, SIGNAL("removeDownload"), self.slotRemoveDownload) - self.connect(self.mainWindow, SIGNAL("abortDownload"), self.slotAbortDownload) - self.connect(self.mainWindow, SIGNAL("addContainer"), self.slotAddContainer) - self.connect(self.mainWindow, SIGNAL("stopAllDownloads"), self.slotStopAllDownloads) - self.connect(self.mainWindow, SIGNAL("setClipboardStatus"), self.slotSetClipboardStatus) - self.connect(self.mainWindow, SIGNAL("changePackageName"), self.slotChangePackageName) - self.connect(self.mainWindow, SIGNAL("pullOutPackage"), self.slotPullOutPackage) - self.connect(self.mainWindow, SIGNAL("refreshStatus"), self.slotRefreshStatus) - self.connect(self.mainWindow, SIGNAL("reloadAccounts"), self.slotReloadAccounts) - self.connect(self.mainWindow, SIGNAL("Quit"), self.slotQuit) - - self.connect(self.mainWindow.mactions["exit"], SIGNAL("triggered()"), self.slotQuit) - self.connect(self.mainWindow.captchaDock, SIGNAL("done"), self.slotCaptchaDone) - - def slotShowConnector(self): - """ - emitted from main window (menu) - hide the main window and show connection manager - (to switch to other core) - """ - self.quitInternal() - self.stopMain() - self.init() - - #def quit(self): #not used anymore? - # """ - # quit gui - # """ - # self.app.quit() - - def loop(self): - """ - start application loop - """ - sys.exit(self.app.exec_()) - - def slotErrorBox(self, msg): - """ - display a nice error box - """ - msgb = QMessageBox(QMessageBox.Warning, "Error", msg) - msgb.exec_() - - def initPackageCollector(self): - """ - init the package collector view - * columns - * selection - * refresh thread - * drag'n'drop - """ - view = self.mainWindow.tabs["collector"]["package_view"] - view.setSelectionBehavior(QAbstractItemView.SelectRows) - view.setSelectionMode(QAbstractItemView.ExtendedSelection) - def dropEvent(klass, event): - event.setDropAction(Qt.CopyAction) - event.accept() - view = event.source() - if view == klass: - items = view.selectedItems() - for item in items: - if not hasattr(item.parent(), "getPackData"): - continue - target = view.itemAt(event.pos()) - if not hasattr(target, "getPackData"): - target = target.parent() - klass.emit(SIGNAL("droppedToPack"), target.getPackData()["id"], item.getFileData()["id"]) - event.ignore() - return - items = view.selectedItems() - for item in items: - row = view.indexOfTopLevelItem(item) - view.takeTopLevelItem(row) - def dragEvent(klass, event): - #view = event.source() - #dragOkay = False - #items = view.selectedItems() - #for item in items: - # if hasattr(item, "_data"): - # if item._data["id"] == "fixed" or item.parent()._data["id"] == "fixed": - # dragOkay = True - # else: - # dragOkay = True - #if dragOkay: - event.accept() - #else: - # event.ignore() - view.dropEvent = dropEvent - view.dragEnterEvent = dragEvent - view.setDragEnabled(True) - view.setDragDropMode(QAbstractItemView.DragDrop) - view.setDropIndicatorShown(True) - view.setDragDropOverwriteMode(True) - view.connect(view, SIGNAL("droppedToPack"), self.slotAddFileToPackage) - #self.packageCollector = PackageCollector(view, self.connector) - self.packageCollector = view.model() - - def initQueue(self): - """ - init the queue view - * columns - * progressbar - """ - view = self.mainWindow.tabs["queue"]["view"] - view.setSelectionBehavior(QAbstractItemView.SelectRows) - view.setSelectionMode(QAbstractItemView.ExtendedSelection) - self.queue = view.model() - self.connect(self.queue, SIGNAL("updateCount"), self.slotUpdateCount) - overview = self.mainWindow.tabs["overview"]["view"].model() - overview.queue = self.queue - self.connect(self.queue, SIGNAL("updateCount"), overview.queueChanged) - self.queue.start() - - def slotUpdateCount(self, pc, fc): - self.mainWindow.packageCount.setText("%i" % pc) - self.mainWindow.fileCount.setText("%i" % fc) - - def refreshServerStatus(self): - """ - refresh server status and overall speed in the status bar - """ - s = self.connector.statusServer() - if s.pause: - self.mainWindow.status.setText(_("paused")) - else: - self.mainWindow.status.setText(_("running")) - self.mainWindow.speed.setText(formatSpeed(s.speed)) - self.mainWindow.space.setText(formatSize(self.serverStatus["freespace"])) - self.mainWindow.actions["toggle_status"].setChecked(not s.pause) - - def refreshLog(self): - """ - update log window - """ - offset = self.mainWindow.tabs["log"]["text"].logOffset - lines = self.connector.getLog(offset) - if not lines: - return - self.mainWindow.tabs["log"]["text"].logOffset += len(lines) - for line in lines: - self.mainWindow.tabs["log"]["text"].emit(SIGNAL("append(QString)"), line.strip("\n")) - cursor = self.mainWindow.tabs["log"]["text"].textCursor() - cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) - self.mainWindow.tabs["log"]["text"].setTextCursor(cursor) - - def getConnections(self): - """ - parse all connections in the config file - """ - connectionsNode = self.parser.xml.elementsByTagName("connections").item(0) - if connectionsNode.isNull(): - raise Exception("null") - connections = self.parser.parseNode(connectionsNode) - ret = [] - for conn in connections: - data = {} - data["type"] = conn.attribute("type", "remote") - data["default"] = conn.attribute("default", "False") - data["id"] = conn.attribute("id", uuid().hex) - if data["default"] == "True": - data["default"] = True - else: - data["default"] = False - subs = self.parser.parseNode(conn, "dict") - if not subs.has_key("name"): - data["name"] = _("Unnamed") - else: - data["name"] = subs["name"].text() - if data["type"] == "remote": - if not subs.has_key("server"): - continue - else: - data["host"] = subs["server"].text() - data["user"] = subs["server"].attribute("user", "admin") - data["port"] = int(subs["server"].attribute("port", "7227")) - data["password"] = subs["server"].attribute("password", "") - ret.append(data) - return ret - - def slotSaveConnection(self, data): - """ - save connection to config file - """ - connectionsNode = self.parser.xml.elementsByTagName("connections").item(0) - if connectionsNode.isNull(): - raise Exception("null") - connections = self.parser.parseNode(connectionsNode) - connNode = self.parser.xml.createElement("connection") - connNode.setAttribute("default", str(data["default"])) - connNode.setAttribute("type", data["type"]) - connNode.setAttribute("id", data["id"]) - nameNode = self.parser.xml.createElement("name") - nameText = self.parser.xml.createTextNode(data["name"]) - nameNode.appendChild(nameText) - connNode.appendChild(nameNode) - if data["type"] == "remote": - serverNode = self.parser.xml.createElement("server") - serverNode.setAttribute("user", data["user"]) - serverNode.setAttribute("port", data["port"]) - serverNode.setAttribute("password", data["password"]) - hostText = self.parser.xml.createTextNode(data["host"]) - serverNode.appendChild(hostText) - connNode.appendChild(serverNode) - found = False - for c in connections: - cid = c.attribute("id", "None") - if str(cid) == str(data["id"]): - found = c - break - if found: - connectionsNode.replaceChild(connNode, found) - else: - connectionsNode.appendChild(connNode) - self.parser.saveData() - self.refreshConnections() - - def slotRemoveConnection(self, data): - """ - remove connection from config file - """ - connectionsNode = self.parser.xml.elementsByTagName("connections").item(0) - if connectionsNode.isNull(): - raise Exception("null") - connections = self.parser.parseNode(connectionsNode) - found = False - for c in connections: - cid = c.attribute("id", "None") - if str(cid) == str(data["id"]): - found = c - break - if found: - connectionsNode.removeChild(found) - self.parser.saveData() - self.refreshConnections() - - def slotConnect(self, data): - """ - connect to a core - if connection is local, parse the core config file for data - if internal, start pyLoadCore - set up connector, show main window - """ - self.connWindow.hide() - if data["type"] not in ("remote","internal"): - - coreparser = ConfigParser(self.configdir) - if not coreparser.config: - self.connector.setConnectionData("127.0.0.1", 7227, "anonymous", "anonymous", False) - else: - self.connector.setConnectionData("127.0.0.1", coreparser.get("remote","port"), "anonymous", "anonymous") - - elif data["type"] == "remote": - self.connector.setConnectionData(data["host"], data["port"], data["user"], data["password"]) - - elif data["type"] == "internal": - from pyLoadCore import Core - from module.ConfigParser import ConfigParser as CoreConfig - import thread - - if not self.core: - - config = CoreConfig() #create so at least default config exists - self.core = Core() - self.core.startedInGui = True - thread.start_new_thread(self.core.start, (False, False)) - while not self.core.running: - sleep(0.5) - - self.connector.proxy = self.core.api - self.connector.internal = True - - #self.connector.setConnectionData("127.0.0.1", config.get("remote","port"), "anonymous", "anonymous") - - self.startMain() -# try: -# host = data["host"] -# except: -# host = "127.0.0.1" - - def refreshConnections(self): - """ - reload connetions and display them - """ - self.parser.loadData() - conns = self.getConnections() - self.connWindow.emit(SIGNAL("setConnections"), conns) - for conn in conns: - if conn["default"]: - return conn - return None - - def slotSetDownloadStatus(self, status): - """ - toolbar start/pause slot - """ - if status: - self.connector.unpauseServer() - else: - self.connector.pauseServer() - - def slotAddPackage(self, name, links, password=None): - """ - emitted from main window - add package to the collector - """ - pack = self.connector.addPackage(name, links, Destination.Collector) - if password: - data = {"password": password} - self.connector.setPackageData(pack, data) - - def slotAddFileToPackage(self, pid, fid): #TODO deprecated? gets called - """ - emitted from collector view after a drop action - """ - #self.connector.addFileToPackage(fid, pid) - pass - - def slotAddContainer(self, path): - """ - emitted from main window - add container - """ - filename = basename(path) - #type = "".join(filename.split(".")[-1]) - fh = open(path, "r") - content = fh.read() - fh.close() - self.connector.uploadContainer(filename, content) - - def slotSaveMainWindow(self, state, geo): - """ - save the window geometry and toolbar/dock position to config file - """ - mainWindowNode = self.parser.xml.elementsByTagName("mainWindow").item(0) - if mainWindowNode.isNull(): - mainWindowNode = self.parser.xml.createElement("mainWindow") - self.parser.root.appendChild(mainWindowNode) - stateNode = mainWindowNode.toElement().elementsByTagName("state").item(0) - geoNode = mainWindowNode.toElement().elementsByTagName("geometry").item(0) - newStateNode = self.parser.xml.createTextNode(state) - newGeoNode = self.parser.xml.createTextNode(geo) - - stateNode.removeChild(stateNode.firstChild()) - geoNode.removeChild(geoNode.firstChild()) - stateNode.appendChild(newStateNode) - geoNode.appendChild(newGeoNode) - - self.parser.saveData() - - def restoreMainWindow(self): - """ - load and restore main window geometry and toolbar/dock position from config - """ - mainWindowNode = self.parser.xml.elementsByTagName("mainWindow").item(0) - if mainWindowNode.isNull(): - return - nodes = self.parser.parseNode(mainWindowNode, "dict") - - state = str(nodes["state"].text()) - geo = str(nodes["geometry"].text()) - - self.mainWindow.restoreWindow(state, geo) - self.mainWindow.captchaDock.hide() - - def slotPushPackageToQueue(self, id): - """ - emitted from main window - push the collector package to queue - """ - self.connector.pushToQueue(id) - - def slotRestartDownload(self, id, isPack): - """ - emitted from main window - restart download - """ - if isPack: - self.connector.restartPackage(id) - else: - self.connector.restartFile(id) - - def slotRefreshStatus(self, id): - """ - emitted from main window - refresh download status - """ - self.connector.recheckPackage(id) - - def slotRemoveDownload(self, id, isPack): - """ - emitted from main window - remove download - """ - if isPack: - self.connector.deletePackages([id]) - else: - self.connector.deleteFiles([id]) - - def slotAbortDownload(self, id, isPack): - """ - emitted from main window - remove download - """ - if isPack: - data = self.connector.getFileOrder(id) #less data to transmit - self.connector.stopDownloads(data.values()) - else: - self.connector.stopDownloads([id]) - - def slotStopAllDownloads(self): - """ - emitted from main window - stop all running downloads - """ - self.connector.stopAllDownloads() - - def slotClipboardChange(self): - """ - called if clipboard changes - """ - if self.checkClipboard: - text = self.clipboard.text() - pattern = re.compile(r"(http|https|ftp)://[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?/.*)?") - matches = pattern.finditer(text) - - # thanks to: jmansour //#139 - links = [str(match.group(0)) for match in matches] - if len(links) == 0: - return - - filenames = [link.rpartition("/")[2] for link in links] - - packagename = commonprefix(filenames) - if len(packagename) == 0: - packagename = filenames[0] - - self.slotAddPackage(packagename, links) - - def slotSetClipboardStatus(self, status): - """ - set clipboard checking - """ - self.checkClipboard = status - - def slotChangePackageName(self, pid, name): - """ - package name edit finished - """ - self.connector.setPackageName(pid, str(name)) - - def slotPullOutPackage(self, pid): - """ - pull package out of the queue - """ - self.connector.pullFromQueue(pid) - - def checkCaptcha(self): - if self.connector.isCaptchaWaiting() and self.mainWindow.captchaDock.isFree(): - t = self.connector.getCaptchaTask(False) - self.mainWindow.show() - self.mainWindow.raise_() - self.mainWindow.activateWindow() - self.mainWindow.captchaDock.emit(SIGNAL("setTask"), t.tid, b64decode(t.data), t.type) - elif not self.mainWindow.captchaDock.isFree(): - status = self.connector.getCaptchaTaskStatus(self.mainWindow.captchaDock.currentID) - if not (status == "user" or status == "shared-user"): - self.mainWindow.captchaDock.hide() - self.mainWindow.captchaDock.processing = False - self.mainWindow.captchaDock.currentID = None - - def slotCaptchaDone(self, cid, result): - self.connector.setCaptchaResult(cid, str(result)) - - def pullEvents(self): - events = self.connector.getEvents(self.connector.connectionID) - if not events: - return - for event in events: - if event.eventname == "account": - self.mainWindow.emit(SIGNAL("reloadAccounts"), False) - elif event.eventname == "config": - pass - elif event.destination == Destination.Queue: - self.queue.addEvent(event) - try: - if event.eventname == "update" and event.type == ElementType.File: - info = self.connector.getFileData(event.id) - if info.statusmsg == "finished": - self.emit(SIGNAL("showMessage"), _("Finished downloading of '%s'") % info.name) - elif info.statusmsg == "failed": - self.emit(SIGNAL("showMessage"), _("Failed downloading '%s'!") % info.name) - if event.event == "insert" and event.type == ElementType.File: - info = self.connector.getLinkInfo(event[3]) - self.emit(SIGNAL("showMessage"), _("Added '%s' to queue") % info.name) - except: - print "can't send notification" - elif event.destination == Destination.Collector: - self.packageCollector.addEvent(event) - - def slotReloadAccounts(self, force=False): - self.mainWindow.tabs["accounts"]["view"].model().reloadData(force) - - def slotQuit(self): - self.tray.hide() - self.quitInternal() - self.app.quit() - - def quitInternal(self): - if self.core: - self.core.api.kill() - for i in range(10): - if self.core.shuttedDown: - break - sleep(0.5) - - def slotConnectionLost(self): - if not self.connectionLost: - self.connectionLost = True - m = QMessageBox(QMessageBox.Critical, _("Connection lost"), _("Lost connection to the core!"), QMessageBox.Ok) - m.exec_() - self.slotQuit() - - class Loop(): - def __init__(self, parent): - self.parent = parent - self.timer = QTimer() - self.timer.connect(self.timer, SIGNAL("timeout()"), self.update) - self.lastSpaceCheck = 0 - - def start(self): - self.update() - self.timer.start(1000) - - def update(self): - """ - methods to call - """ - self.parent.refreshServerStatus() - if self.lastSpaceCheck + 5 < time(): - self.lastSpaceCheck = time() - self.parent.serverStatus["freespace"] = self.parent.connector.freeSpace() - self.parent.refreshLog() - self.parent.checkCaptcha() - self.parent.pullEvents() - - def stop(self): - self.timer.stop() - - -class TrayIcon(QSystemTrayIcon): - def __init__(self): - QSystemTrayIcon.__init__(self, QIcon(join(pypath, "icons", "logo-gui.png"))) - self.contextMenu = QMenu() - self.showAction = QAction(_("Show"), self.contextMenu) - self.showAction.setCheckable(True) - self.showAction.setChecked(True) - self.showAction.setDisabled(True) - self.contextMenu.addAction(self.showAction) - self.exitAction = QAction(QIcon(join(pypath, "icons", "close.png")), _("Exit"), self.contextMenu) - self.contextMenu.addAction(self.exitAction) - self.setContextMenu(self.contextMenu) - - self.connect(self, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.clicked) - - def mainWindowHidden(self): - self.showAction.setChecked(False) - - def clicked(self, reason): - if self.showAction.isEnabled(): - if reason == QSystemTrayIcon.Trigger: - self.showAction.toggle() - -class Notification(QObject): - def __init__(self, tray): - QObject.__init__(self) - self.tray = tray - self.usePynotify = False - - try: - self.usePynotify = pynotify.init("icon-summary-body") - except: - print "init error" - - def showMessage(self, body): - if self.usePynotify: - n = pynotify.Notification("pyload", body, join(pypath, "icons", "logo.png")) - try: - n.set_hint_string("x-canonical-append", "") - except: - pass - n.show() - else: - self.tray.showMessage("pyload", body) - -if __name__ == "__main__": - renameProcess('pyLoadGui') - app = main() - app.loop() - diff --git a/pyload-cli.py b/pyload-cli.py new file mode 100644 index 000000000..c1e2ff617 --- /dev/null +++ b/pyload-cli.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.cli.Cli import main + +if __name__ == "__main__": + main() diff --git a/pyload.py b/pyload.py new file mode 100644 index 000000000..b53bf4352 --- /dev/null +++ b/pyload.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.Core import main + +if __name__ == "__main__": + main() diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000..6fd0b168c --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,23 @@ +Script Support +-------------- + +pyLoad is able to start any kind of scripts at given events. +Simply put your script in a suitable folder and pyLoad will execute it at the given events and pass some arguments to them. + + +***Note:*** +**Every script starting with symbol `#` will be ignored!** (ex.: `#converter.sh`) + +***Note:*** +You have to restart pyload when you change script names or locations. + + +Below you see the list of arguments, which are passed to the scripts. + +### Argument list + + - `download_preparing`: **`pluginname` `url`** + - `download_finished`: **`pluginname` `url` `filename` `filelocation`** + - `package_finshed`: **`packagename` `packagelocation`** + - `before_reconnect`: **`oldip`** + - `after_reconnect`: **`newip`** diff --git a/scripts/Readme.txt b/scripts/Readme.txt deleted file mode 100644 index 1c326801d..000000000 --- a/scripts/Readme.txt +++ /dev/null @@ -1,25 +0,0 @@ - ############################# - ### pyLoad Script Support ### - ############################# - -pyLoad is able to start any kind of scripts at given events. -Simply put your script in a suitable folder and pyLoad will execute it at the given events and pass some arguments to them. - ---> Note: Scripts, which starts with # will be ignored! -For Example: #converter.sh will not be executed. - ---> Note: You have to restart pyload when you change script names or locations. - -Below you see the list of arguments, which are passed to the scripts. - -## Argument list ## - -download_preparing: pluginname url - -download_finished: pluginname url filename filelocation - -package_finshed: packagename packagelocation - -before_reconnect: oldip - -after_reconnect: newip
\ No newline at end of file diff --git a/scripts/clonedigger.sh b/scripts/clonedigger.sh new file mode 100644 index 000000000..87c3437cf --- /dev/null +++ b/scripts/clonedigger.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +PYLOAD="../module" # Check ~/pyload/module directory +clonedigger -o cpd.xml --cpd-output --fast --ignore-dir="lib" --ignore-dir="remote" $PYLOAD diff --git a/scripts/code_analysis.sh b/scripts/code_analysis.sh new file mode 100644 index 000000000..dce93d63d --- /dev/null +++ b/scripts/code_analysis.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +PYLOAD="../module" # Check ~/pyload/module directory + +echo "Running sloccount ..." +REPORT="sloccount.sc" +sloccount --duplicates --wide --details $PYLOAD > $REPORT && echo "Done. Report saved to $REPORT" + +echo "Running pep8 ..." +REPORT="pep8.txt" +pep8 $PYLOAD > $REPORT && echo "Done. Report saved to $REPORT" + +echo "Running pylint ..." +REPORT="pylint.txt" +pylint --reports=no $PYLOAD > $REPORT && echo "Done. Report saved to $REPORT" + +#echo "Running pyflakes ..." +#REPORT="pyflakes.txt" +#{ + # pyflakes to pylint syntak +# find $PYLOAD -type f -name "*.py" | egrep -v '^\./lib' | xargs pyflakes > pyflakes.log || : + # Filter warnings and strip ./ from path +# cat pyflakes.log | awk -F\: '{printf "%s:%s: [E]%s\n", $1, $2, $3}' | grep -i -E -v "'_'|pypath|webinterface|pyreq|addonmanager" > $REPORT +# sed -i 's/^.\///g' $REPORT +#} && echo "Done. Report saved to $REPORT" diff --git a/systemCheck.py b/systemCheck.py deleted file mode 100644 index 60fe0313b..000000000 --- a/systemCheck.py +++ /dev/null @@ -1,142 +0,0 @@ -import os -import subprocess -import sys - -#from module import InitHomeDir - -#very ugly prints, but at least it works with python 3 - -def main(): - print("##### System Information #####\n") - print("Platform:", sys.platform) - print("Operating System:", os.name) - print("Python:", sys.version.replace("\n", "")+ "\n") - - try: - import pycurl - print("pycurl:", pycurl.version) - except: - print("pycurl:", "missing") - - try: - import Crypto - print("py-crypto:", Crypto.__version__) - except: - print("py-crypto:", "missing") - - - try: - import OpenSSL - print("OpenSSL:", OpenSSL.version.__version__) - except: - print("OpenSSL:", "missing") - - try: - import Image - print("image libary:", Image.VERSION) - except: - print("image libary:", "missing") - - try: - import PyQt4.QtCore - print("pyqt:", PyQt4.QtCore.PYQT_VERSION_STR) - except: - print("pyqt:", "missing") - - print("\n\n##### System Status #####") - print("\n## pyLoadCore ##") - - core_err = [] - core_info = [] - - if sys.version_info > (2, 8): - core_err.append("Your python version is to new, Please use Python 2.6/2.7") - - if sys.version_info < (2, 5): - core_err.append("Your python version is to old, Please use at least Python 2.5") - - try: - import pycurl - except: - core_err.append("Please install py-curl to use pyLoad.") - - - try: - from pycurl import AUTOREFERER - except: - core_err.append("Your py-curl version is to old, please upgrade!") - - try: - import Image - except: - core_err.append("Please install py-imaging/pil to use Hoster, which uses captchas.") - - pipe = subprocess.PIPE - try: - p = subprocess.call(["tesseract"], stdout=pipe, stderr=pipe) - except: - core_err.append("Please install tesseract to use Hoster, which uses captchas.") - - try: - import OpenSSL - except: - core_info.append("Install OpenSSL if you want to create a secure connection to the core.") - - if core_err: - print("The system check has detected some errors:\n") - for err in core_err: - print(err) - else: - print("No Problems detected, pyLoadCore should work fine.") - - if core_info: - print("\nPossible improvements for pyload:\n") - for line in core_info: - print(line) - - - print("\n## pyLoadGui ##") - - gui_err = [] - - try: - import PyQt4 - except: - gui_err.append("GUI won't work without pyqt4 !!") - - if gui_err: - print("The system check has detected some errors:\n") - for err in gui_err: - print(err) - else: - print("No Problems detected, pyLoadGui should work fine.") - - - print("\n## Webinterface ##") - - web_err = [] - web_info = [] - - try: - import flup - except: - web_info.append("Install Flup to use FastCGI or optional webservers.") - - - if web_err: - print("The system check has detected some errors:\n") - for err in web_err: - print(err) - else: - print("No Problems detected, Webinterface should work fine.") - - if web_info: - print("\nPossible improvements for webinterface:\n") - for line in web_info: - print(line) - - -if __name__ == "__main__": - main() - - raw_input("Press Enter to Exit.") diff --git a/testlinks.txt b/testlinks.txt deleted file mode 100644 index 428cf63ea..000000000 --- a/testlinks.txt +++ /dev/null @@ -1,26 +0,0 @@ -sha1: - 961486646bf3c1d5d7a45ec32bb62e1bc4f2d894 random.bin -md5: - d76505d0869f9f928a17d42d66326307 random.bin - -please save bandwith on our server, -use this link only for remote uploads to new hoster -http://get.pyload.org/static/random.bin ---------------------------------------- -http://netload.in/datei9XirAJZs79/random.bin.htm -http://ul.to/file/o41isx -http://rapidshare.com/files/445996776/random.bin -http://dl.free.fr/d4aL5dyXY -http://www.duckload.com/dl/QggW2 -http://files.mail.ru/32EW66 -http://www.fileserve.com/file/MxjZXjX -http://www.4shared.com/file/-O5CBhQV/random.html -http://hotfile.com/dl/101569859/2e01f04/random.bin.html -http://www.megaupload.com/?d=1JZLOP3B -http://www.share.cx/files/235687689252/random.bin.html -http://www.share-online.biz/download.php?id=PTCOX1GL6XAH -http://www.shragle.com/files/f899389b/random.bin -http://www10.zippyshare.com/v/76557688/file.html -http://yourfiles.to/?d=312EC6E911 -http://depositfiles.com/files/k8la98953 -http://uploading.com/files/3896f5a1/random.bin/ |